# 04. Authentication & Session Security Hardening meta: id: web-production-04 feature: web-production priority: P1 depends_on: [] tags: [security, auth, production] objective: - Harden authentication and session management to prevent session hijacking, fixation, and brute force attacks deliverables: - Secure session configuration - JWT hardening - Brute force protection - Session invalidation on logout - Multi-factor authentication foundation steps: 1. Harden JWT implementation in web/src/server/auth/jwt.ts: - Remove fallback secret (currently uses dev secret if env missing) - Add JWT issuer and audience claims - Implement token blacklisting for logout - Add refresh token rotation 2. Harden session management in web/src/server/auth/session.ts: - Use httpOnly, secure, sameSite=strict cookies - Add session fingerprinting (user agent hash) - Implement concurrent session limits (max 5 per user) - Add automatic session expiry refresh on activity 3. Add brute force protection: - Track failed login attempts per IP/email - Progressive delays: 1s, 2s, 4s, 8s, 16s - Lock account after 10 failed attempts (1 hour) 4. Implement secure logout: - Invalidate session in database - Clear all cookies - Blacklist JWT token - Revoke refresh token 5. Add MFA foundation: - TOTP secret generation - QR code for authenticator apps - Backup codes 6. Audit Clerk integration for security: - Verify webhook signature validation - Check Clerk session sync with custom sessions tests: - Unit: Test JWT signing/verification with invalid tokens - Integration: Test brute force lockout, session expiry - Security: Test session hijacking resistance acceptance_criteria: - No hardcoded or fallback secrets in auth code - All cookies have httpOnly, secure, sameSite=strict - Brute force protection active on login endpoints - Logout invalidates session completely - JWT tokens include iss, aud, iat, exp claims - Session fingerprinting prevents cookie theft reuse - MFA TOTP generation working with Google Authenticator validation: - Attempt 10 failed logins → account locked - Steal session cookie from one browser → invalid in another (fingerprinting) - Logout → session token rejected on subsequent requests - Check JWT with jwt.io → valid iss and aud claims notes: - Current JWT has fallback secret — this is critical to fix before production - Clerk handles frontend auth but backend needs its own hardening - Consider using Lucia Auth or NextAuth patterns for session management