Authentication

TurboStack includes a production-ready authentication system with JWT tokens, sessions, email verification, and password reset.

Features

JWT Tokens

Short-lived access tokens with refresh mechanism

Session Management

Secure httpOnly cookie-based sessions

Email Verification

Verify users before granting full access

Password Reset

Secure token-based password recovery

Rate Limiting

Protection against brute force attacks

Argon2 Hashing

Industry-standard password security

API Endpoints

EndpointMethodDescriptionAuth Required
/auth/registerPOSTCreate new account
/auth/loginPOSTAuthenticate user
/auth/logoutPOSTEnd session
/auth/refreshPOSTRefresh access token🍪 Cookie
/auth/meGETGet current user
/auth/verify-emailGETVerify email address
/auth/forgot-passwordPOSTRequest password reset
/auth/reset-passwordPOSTReset password

Usage Examples

const response = await fetch("http://localhost:4101/auth/register", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    email: "user@example.com",
    name: "John Doe",
    password: "securepassword123",
  }),
});

const data = await response.json();
// {
//   success: true,
//   message: "Registration successful. Check your email.",
//   data: { user: { id, email, name } }
// }

Token Management

Access Token (JWT)

PropertyValue
Lifetime15 minutes
StorageMemory (not persisted)
UsageAPI requests via Authorization header
ContainsuserId, email, role, expiry
// Payload structure
{
  sub: "user_123",         // User ID
  email: "user@example.com",
  role: "USER",
  iat: 1704067200,         // Issued at
  exp: 1704068100          // Expires (15 min)
}
PropertyValue
Lifetime7 days
StoragehttpOnly cookie
UsageGet new access tokens
SecurityhttpOnly, secure, sameSite=lax
PropertyValue
Lifetime7 days
StoragehttpOnly cookie
UsageBackend session validation
SecurityhttpOnly, secure, sameSite=lax

Security Features

Password Hashing

Uses Argon2 - the winner of the Password Hashing Competition:
import { hash, verify } from "@node-rs/argon2";

// Hashing
const hashedPassword = await hash(password, {
  memoryCost: 65536,  // 64MB
  timeCost: 3,        // 3 iterations
  parallelism: 4,     // 4 parallel threads
});

// Verification
const isValid = await verify(hashedPassword, password);

Rate Limiting

Authentication endpoints are protected:
const authRateLimiter = rateLimit({
  duration: 60 * 1000, // 1 minute window
  max: 5, // 5 attempts max
  scoping: "scoped", // Per-IP limiting
});
After 5 failed login attempts, the IP is blocked for 1 minute. This prevents brute force attacks.

Email Verification Flow

1

User Registers

Account created with emailVerified: null
2

Verification Email Sent

Email with unique token sent via Resend
3

User Clicks Link

GET /auth/verify-email?token=xxx
4

Email Verified

emailVerified updated to current timestamp

Password Reset Flow

1

User Requests Reset

POST /auth/forgot-password with email
2

Reset Email Sent

Email with secure reset link (valid 1 hour)
3

User Sets New Password

POST /auth/reset-password with token & new password
4

Password Updated

Old sessions invalidated, user can login

Environment Variables

# JWT Configuration
JWT_SECRET=your-super-secret-key-min-32-chars

# Session Configuration
SESSION_SECRET=another-super-secret-key

# Email (for verification & reset)
RESEND_API_KEY=re_your_api_key
FROM_EMAIL=noreply@yourdomain.com

# App Configuration
APP_NAME=TurboStack
FRONTEND_URL=http://localhost:4100
NODE_ENV=development

Best Practices

DO

  • ✅ Use HTTPS in production - ✅ Require email verification - ✅ Implement rate limiting - ✅ Use httpOnly cookies - ✅ Rotate tokens regularly - ✅ Hash passwords with Argon2

DON'T

  • ❌ Store tokens in localStorage - ❌ Send passwords in URL - ❌ Skip input validation - ❌ Use weak JWT secrets - ❌ Disable rate limiting - ❌ Log sensitive data
Use the built-in AuthGuard component on the frontend to protect pages that require authentication.