Basic Authentication System (ST-104)
Overview
Implements user registration and login with password-based authentication. Users can create accounts, log in securely, and receive session tokens. Passwords are hashed using bcrypt, and sessions are managed via JWT tokens stored in HTTP-only cookies.
Features
- User registration with email and password
- Email verification (token-based)
- Secure password hashing (bcrypt)
- Password reset functionality
- Session management with JWT tokens
- HTTP-only session cookies
- Rate limiting on authentication endpoints
- Brute force protection
- Audit logging for authentication events
API Endpoints
Register
POST /api/auth/register
Creates a new user account.
Request Body:
{
"email": "user@example.com",
"password": "SecurePassword123!"
}
Response:
{
"ok": true
}
Response (with email verification):
{
"ok": true,
"message": "User registered successfully. Please check your email to verify your account."
}
Status Codes:
201- Registration successful400- Validation error409- Email already exists429- Rate limit exceeded
Note: In development mode, the response includes verificationToken and verificationUrl for testing purposes.
Login
POST /api/auth/login
Authenticates a user and creates a session.
Request Body:
{
"email": "user@example.com",
"password": "SecurePassword123!"
}
Response:
{
"ok": true
}
Status Codes:
200- Login successful400- Validation error401- Invalid credentials429- Rate limit exceeded or account locked
Password Reset Request
POST /api/auth/password-reset/request
Request a password reset token for a user account.
Request Body:
{
"email": "user@example.com"
}
Response:
{
"message": "If an account with that email exists, a password reset link has been sent."
}
Status Codes:
200- Request processed (always returns success to prevent email enumeration)400- Validation error429- Rate limit exceeded
Note: In development mode, the response includes token and resetUrl for testing purposes.
Password Reset Confirm
POST /api/auth/password-reset/confirm
Confirm password reset and update password.
Request Body:
{
"token": "verification-token-from-email",
"password": "NewSecurePassword123!"
}
Response:
{
"message": "Password has been reset successfully. You can now log in with your new password."
}
Status Codes:
200- Password reset successful400- Invalid or expired token, or validation error429- Rate limit exceeded
Email Verification
POST /api/auth/verify-email
Verify email address with verification token.
Request Body:
{
"token": "verification-token-from-email"
}
Response:
{
"message": "Email address verified successfully.",
"verified": true
}
Status Codes:
200- Email verified successfully400- Invalid or expired token429- Rate limit exceeded
Resend Email Verification
POST /api/auth/resend-verification
Resend email verification token. Requires authentication.
Request Body:
None (uses authenticated user's email)
Response:
{
"message": "Verification email has been sent. Please check your email."
}
Status Codes:
200- Verification email sent401- Unauthorized (not authenticated)404- User not found or email not set429- Rate limit exceeded
Note: In development mode, the response includes verificationToken and verificationUrl for testing purposes.
Password Requirements
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character
- Maximum 128 characters
Security Features
Password Hashing
- Uses bcrypt with configurable rounds
- Passwords are never stored in plain text
- Hash stored in user preferences (temporary, will migrate to Account model)
Session Management
- JWT tokens with expiration
- HTTP-only cookies (prevents XSS)
- Secure flag in production (HTTPS only)
- SameSite=Lax for CSRF protection
Rate Limiting
- Registration: 5 requests per 15 minutes
- Login: 10 requests per 15 minutes
- Configurable via environment variables
Brute Force Protection
- Tracks failed login attempts by IP and email
- Locks account after 5 failed attempts (default)
- Lock duration: 15 minutes (default)
- Automatically clears on successful login
Implementation Details
Registration Flow
- Validate request body (Zod schema)
- Check rate limits
- Verify email doesn't exist
- Hash password with bcrypt
- Create user record with
emailVerified: false - Generate email verification token (24-hour expiration)
- Queue verification email (for future email infrastructure)
- Create session JWT
- Set session cookie
- Log audit event
Login Flow
- Validate request body (Zod schema)
- Check rate limits
- Check brute force lock status
- Find user by email
- Verify password hash
- Record failed attempt if invalid
- Update last login timestamp
- Create session JWT
- Set session cookie
- Log audit event
Data Model
User Table
id- UUID primary keyemail- User email (optional, nullable)preferences- JSONB field storing password hash temporarilycreatedAt- Account creation timestamplastLoginAt- Last successful login timestamp
Session Table
id- UUID primary keyuserId- Foreign key to userssessionToken- JWT token stringexpires- Token expiration timestampcreatedAt- Session creation timestamp
Environment Variables
# JWT secret for signing tokens
JWT_SECRET=your-secret-key
# Session expiration (seconds)
SESSION_EXPIRES_IN=86400 # 24 hours
# Bcrypt rounds
BCRYPT_ROUNDS=10
Usage
Register a User
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePassword123!',
}),
});
Login
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePassword123!',
}),
});
// Session cookie is automatically set
Check Authentication
import { getSession } from '@/lib/server/auth';
const session = await getSession(request);
if (session) {
// User is authenticated
const userId = session.sub;
}
Audit Logging
All authentication events are logged:
user_created- User registrationlogin_success- Successful loginlogin_failure- Failed login attemptconfig_updated- Password reset requested/completed, email verification completed
Audit logs include:
- User ID (if available)
- IP address
- User agent
- Timestamp
- Metadata (email, reason for failure)
Testing
Unit Tests
Location: apps/web/src/lib/server/__tests__/password.test.ts
Tests cover:
- Password hashing
- Password verification
- Invalid password handling
Integration Tests
Location: apps/web/src/app/api/auth/__tests__/
Tests cover:
- Registration flow
- Login flow
- Error handling
- Rate limiting
- Brute force protection
Password Reset Flow
- User requests password reset via email
- System generates secure token (hashed before storage)
- Token sent via email (queued for future email infrastructure)
- User confirms reset with token and new password
- Password updated and token marked as used
Password Reset Security
- Tokens are cryptographically secure (32-byte random)
- Tokens hashed with bcrypt (10 rounds) before storage
- Rate limiting prevents abuse
- Prevents email enumeration (always returns success)
- Invalidates existing tokens when new one is created
- Single-use tokens (marked as used after confirmation)
- Automatic token expiration (1 hour)
Email Verification Flow
- User registers account
- System generates verification token (24-hour expiration)
- Token sent via email (queued for future email infrastructure)
- User clicks verification link or submits token
- Email marked as verified in user preferences
Email Verification Security
- Tokens are cryptographically secure (32-byte random)
- Rate limiting prevents abuse
- Single-use tokens (deleted after verification)
- Automatic token expiration (24 hours)
- Invalidates existing tokens when new one is created
Future Enhancements
- Two-factor authentication (2FA)
- Account model migration (separate password provider)
- OAuth integration (see ST-207)
- Session refresh tokens
- Remember me functionality
- Email infrastructure for sending verification and reset emails
Related Documentation
- Input Validation - Validation rules
- Rate Limiting - Rate limit details
- OAuth Integration - OAuth authentication
- Audit Logging - Audit log details