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
| Endpoint | Method | Description | Auth Required |
|---|
/auth/register | POST | Create new account | ❌ |
/auth/login | POST | Authenticate user | ❌ |
/auth/logout | POST | End session | ✅ |
/auth/refresh | POST | Refresh access token | 🍪 Cookie |
/auth/me | GET | Get current user | ✅ |
/auth/verify-email | GET | Verify email address | ❌ |
/auth/forgot-password | POST | Request password reset | ❌ |
/auth/reset-password | POST | Reset password | ❌ |
Usage Examples
Register
Login
Protected Request
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 } }
// }
const response = await fetch("http://localhost:4101/auth/login", {
method: "POST",
credentials: "include", // Important for cookies!
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: "user@example.com",
password: "securepassword123",
}),
});
const data = await response.json();
// {
// success: true,
// data: {
// user: { id, email, name, role },
// accessToken: "eyJhbG..."
// }
// }
const response = await fetch("http://localhost:4101/auth/me", {
method: "GET",
credentials: "include",
headers: {
"Authorization": `Bearer ${accessToken}`,
},
});
const data = await response.json();
// { success: true, data: { user: {...} } }
Token Management
| Property | Value |
|---|
| Lifetime | 15 minutes |
| Storage | Memory (not persisted) |
| Usage | API requests via Authorization header |
| Contains | userId, 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)
}
| Property | Value |
|---|
| Lifetime | 7 days |
| Storage | httpOnly cookie |
| Usage | Get new access tokens |
| Security | httpOnly, secure, sameSite=lax |
| Property | Value |
|---|
| Lifetime | 7 days |
| Storage | httpOnly cookie |
| Usage | Backend session validation |
| Security | httpOnly, 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
User Registers
Account created with emailVerified: null
Verification Email Sent
Email with unique token sent via Resend
User Clicks Link
GET /auth/verify-email?token=xxx
Email Verified
emailVerified updated to current timestamp
Password Reset Flow
User Requests Reset
POST /auth/forgot-password with email
Reset Email Sent
Email with secure reset link (valid 1 hour)
User Sets New Password
POST /auth/reset-password with token & new password
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.