๐ AUTHENTICATION & AUTHORIZATION SYSTEM โ
Overview โ
The auth system implements a comprehensive JWT-based authentication with OAuth 2.0 social login (Google, GitHub), session management, API keys, and security auditing. All auth operations are centralized through services that interact with D1 database.
Core Components:
- AuthService - Main authentication orchestrator
- SessionService - JWT session management with D1 persistence
- JWTUtils - Token creation, verification, signing
- OAuth Providers - Google & GitHub implementations with PKCE
- Middleware - Route protection and token extraction
- Security - Password hashing, rate limiting, audit logs
Auth Architecture Flow โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CLIENT REQUEST โ
โ (Browser / API Client / WebSocket) โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TOKEN EXTRACTION (authUtils.ts) โ
โ Priority: โ
โ 1. Authorization: Bearer <token> (most secure) โ
โ 2. Cookie: accessToken (browser) โ
โ 3. Query: ?token=<token> (WebSocket) โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JWT VERIFICATION (JWTUtils) โ
โ โข Verify signature with JWT_SECRET โ
โ โข Check expiration (exp claim) โ
โ โข Validate payload structure โ
โ โข Extract: userId, email, sessionId โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SESSION VALIDATION (SessionService) โ
โ โข Query sessions table in D1 โ
โ โข Check: isRevoked = false โ
โ โข Check: expiresAt > now โ
โ โข Update lastActivity timestamp โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ USER LOOKUP (AuthService) โ
โ โข Query users table with userId โ
โ โข Check: deletedAt IS NULL โ
โ โข Return AuthUser object โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ REQUEST CONTEXT ENRICHED โ
โ request.user = { id, email, displayName, ... } โ
โ request.session = { sessionId, expiresAt } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโKey Database Tables โ
users Table โ
Stores user identity, OAuth provider info, preferences, and security settings.
Key fields:
- Identity: id, email, username, displayName, avatarUrl
- OAuth: provider (github/google/email), providerId, emailVerified
- Security: passwordHash (email provider only), failedLoginAttempts, lockedUntil
- Preferences: theme, timezone
- Timestamps: createdAt, updatedAt, deletedAt (soft delete)
Indexed on: email, provider+providerId (unique), username
sessions Table โ
Manages JWT sessions with device tracking and revocation support.
Key fields:
- Session ID, userId (FK to users)
- Device tracking: deviceInfo, userAgent, ipAddress
- Token hashes: accessTokenHash, refreshTokenHash (SHA-256)
- Revocation: isRevoked, revokedAt, revokedReason
- Expiry: expiresAt (default 3 days), lastActivity
Configuration: Max 5 sessions per user, 3 concurrent devices
oauthStates Table โ
Temporary storage for OAuth flow state tokens (CSRF protection).
Key fields:
- state (unique CSRF token), provider (google/github)
- codeVerifier (PKCE), redirectUri
- isUsed (one-time use), expiresAt (10 minutes)
Security: Prevents CSRF attacks, implements PKCE flow
apiKeys Table โ
Stores hashed API keys for programmatic access.
Key fields:
- name, keyHash (SHA-256), keyPreview
- scopes (JSON array), isActive
- Usage: lastUsed, requestCount
- Optional: expiresAt
authAttempts Table โ
Audit log for all authentication attempts.
Purpose: Track login/register attempts, detect suspicious activity Fields: identifier (email), attemptType, success, ipAddress, timestamp
verificationOtps Table โ
Email verification codes. The email-OTP verification flow has been removed (users are auto-verified on registration), so nothing reads or writes this table; the table is retained only to avoid a destructive migration.
Fields: email, otp (hashed), used, expiresAt (15 min)
auditLogs Table โ
Detailed audit trail for security events.
Fields: userId, entityType/entityId, action, oldValues/newValues (JSON), ipAddress, userAgent
AuthService - Core Operations โ
Location: /worker/database/services/AuthService.ts
Handles all authentication operations (login, register, OAuth) and delegates session management to SessionService.
register() Flow โ
- Validate email format and password strength (min 8 chars, mixed case, numbers)
- Check email doesn't already exist
- Hash password with bcrypt (12 rounds)
- Create user with emailVerified=true (no OTP currently)
- Auto-login: create session + generate JWT
- Log attempt to authAttempts table
- Return user + accessToken + sessionId
login() Flow โ
- Find user by email (case-insensitive), check not deleted
- Verify passwordHash exists
- Compare password with bcrypt.verify()
- Create session + generate JWT
- Log attempt (success/fail) with IP + user agent
- Return user + accessToken + sessionId
Security: Failed attempts logged, passwords never logged
OAuth Flow โ
Step 1: getOAuthAuthorizationUrl()
- Cleanup expired OAuth states
- Validate redirect URL (same-origin only)
- Generate CSRF state token + PKCE code verifier
- Store in oauthStates table (10 min expiry)
- Build authorization URL with state + code_challenge
- Return URL to redirect user to provider
Step 2: handleOAuthCallback()
- Verify state token (not used, not expired)
- Mark state as used
- Exchange code for tokens using PKCE verifier
- Fetch user info from provider
- Find or create user (update OAuth info if exists)
- Create session + JWT
- Return user + token + intended redirectUrl
Security: CSRF protected, PKCE prevents code interception, one-time state tokens
Other Key Methods โ
getUserForAuth(userId): Fetch user by ID (checks not deleted) - used by middleware
validateTokenAndGetUser(token): Complete pipeline: verify JWT signature โ check expiration โ fetch user โ return user + sessionId
JWTUtils - Token Management โ
Location: /worker/utils/jwtUtils.ts
Singleton class for JWT operations using jose library.
Token payload contains: userId (sub), email, sessionId, type (access/refresh), iat/exp timestamps
Key operations:
- createAccessToken() - Sign JWT with HS256, 3-day expiry
- verifyToken() - Verify signature, check expiration, return payload
- hashToken() - SHA-256 hash for database storage (security: prevents token leakage from DB breaches)
SessionService - Session Management โ
Location: /worker/database/services/SessionService.ts
Config: Max 5 sessions/user, 3-day TTL, max 3 concurrent devices
Key operations:
createSession() - Cleanup old sessions (keep 5 most recent) โ generate session ID โ create JWT โ hash token โ extract request metadata (IP, user agent, Cloudflare headers) โ store in D1
revokeUserSession() - Mark session as revoked with reason
revokeAllUserSessions() - Revoke all user sessions (for password change, security breach)
getUserSessions() - List active sessions (not revoked, not expired)
getUserSecurityStatus() - Analyze security: count active sessions + recent security events โ calculate risk level (high: >5 events/24h or hijacking; medium: >2 events or >3 devices; low: normal)
forceLogoutAllOtherSessions() - Delete all sessions except current (for suspected compromise)
cleanupExpiredSessions() - Delete expired sessions (run via cron)
OAuth Providers โ
Location: /worker/services/oauth/
Abstract base class provides common OAuth 2.0 flow with PKCE.
PKCE Flow:
- Generate code_verifier (random 32 bytes)
- Hash to create code_challenge (SHA-256)
- Send challenge in authorization URL
- Provider stores challenge
- Exchange code + verifier for tokens
- Provider verifies: hash(verifier) === stored_challenge
Purpose: Prevents authorization code interception attacks
Google OAuth โ
- Scopes: openid, email, profile
- Fetches user info from Google API
- Returns: id, email, name, picture, verified_email
- Env vars: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
GitHub OAuth โ
- Scopes: read:user, user:email (minimal, no repo access)
- Special handling: Email not always in /user endpoint, fetches from /user/emails if needed
- Returns: id, email (primary verified), name, avatar_url
- Env vars: GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET
Authentication Middleware โ
Location: /worker/middleware/auth/routeAuth.ts
Three auth levels:
- public - No auth required
- authenticated - Requires valid JWT
- owner-only - Requires ownership of resource (e.g., user can only edit their own apps)
Flow:
- Route declares auth level via
setAuthLevel()middleware enforceAuthRequirement()checks:- Public: pass through
- Authenticated/Owner: extract token โ validate JWT โ fetch user โ check ownership if needed
- User injected into request context:
c.set('user', user) - Route handler executes with authenticated user
Token extraction priority: Authorization header (APIs) โ Cookie (browser) โ Query param (WebSocket)
Security Features โ
Password Security โ
- Hashing: bcrypt with 12 rounds (~250ms, intentionally slow to prevent brute force)
- Validation: Min 8 chars, mixed case, numbers, special chars, not common password, no sequential patterns (12345)
- Strength scoring: 0-4 scale
Rate Limiting โ
- User-configurable limits (default: 100 requests/min)
- Separate limits for auth endpoints
- Tracked per user/IP in Durable Objects or KV
CSRF Protection โ
- OAuth state tokens: cryptographically random, 10-min expiry, one-time use
- Verified on callback to prevent cross-site request forgery
Session Security โ
- Tokens hashed (SHA-256) in database
- 3-day expiry by default
- Device + IP tracking
- Max 5 sessions per user, 3 concurrent devices
- Force logout feature for security incidents
Audit Logging โ
- All auth attempts logged to
authAttemptstable - Includes: IP, user agent, timestamp, success/failure
- Used for security analysis and anomaly detection