# ADR-001: Session-Based Authentication with httpOnly Cookies ## Status Accepted ## Context The application needs an authentication mechanism for the OAuth2 flow with Authentik. We need to decide between: 1. **JWT tokens** stored in localStorage (common SPA pattern) 2. **Session cookies** with httpOnly flag 3. **JWT tokens** in httpOnly cookies ### Constraints - Frontend and API run on different subdomains in production (e.g., `app.example.com` and `api.example.com`) - Must support OAuth2 authorization code flow - Must work with Traefik reverse proxy - Must be secure against XSS attacks ## Decision We will use **session-based authentication with HMAC-signed httpOnly cookies**. ### Implementation 1. After OAuth callback, the API creates a session token (HMAC-SHA256 signed) 2. Token is stored in an httpOnly, Secure, SameSite cookie 3. Frontend never sees or stores the token 4. Cookie is sent automatically with every request via `withCredentials: true` 5. Session is stateless - token contains user_id and expiry ## Consequences ### Positive - **XSS protection**: Token is never exposed to JavaScript - **Simpler frontend**: No token management, refresh logic, or storage - **Immediate revocation**: Can invalidate sessions server-side if needed - **Standards compliant**: Uses well-established cookie security mechanisms - **Works across subdomains**: Cookie domain can be set to parent domain ### Negative - **CSRF risk**: Requires CSRF protection for state-changing operations (mitigated by SameSite=Lax/Strict) - **Less flexible**: Harder to use with non-browser clients (mitigated by API key support if needed) - **Cookie size**: Session token adds ~100 bytes to every request ### Alternatives Considered **JWT in localStorage** - Pros: Simple implementation, works with any client - Cons: Vulnerable to XSS, requires manual token refresh, complex frontend logic - Rejected due to XSS vulnerability **JWT in httpOnly cookies** - Pros: XSS protection, standard JWT benefits - Cons: Complex refresh token rotation, no easy revocation, larger token size - Rejected in favor of simpler session cookies ## Date 2026-05-18 ## Participants - Development Team