# ADR-004: JWT Authentication Strategy ## Status ACCEPTED ## Context We need a stateless authentication mechanism for the API that: 1. Allows users to login with email/password 2. Provides secure token-based sessions 3. Supports token revocation (logout) 4. Handles token refresh without re-login ## Decision We will use **JWT (JSON Web Tokens)** with the following configuration: ### Token Structure - **Access Token**: 15 minute expiration, contains user identity - **Refresh Token**: 7 day expiration, used to obtain new access tokens ### Algorithm - **HS256** for signing (symmetric, simpler setup) - Secret key loaded from environment variable `JWT_SECRET` ### Claims ```json { "sub": "user_uuid", "email": "user@example.com", "role": "user", "iat": 1715030400, "exp": 1715031300, "jti": "unique-token-id" } ``` ### Session Management - Active sessions tracked in **Redis** (keyed by `jti`) - Sessions invalidated on logout - All user sessions invalidated on password change (from F-003) ## Consequences ### Positive - Stateless = horizontal scaling friendly - Short-lived access tokens limit damage if compromised - Refresh tokens allow long sessions without storing passwords - Redis-based session tracking enables instant revocation ### Negative - Cannot revoke individual refresh tokens (need blocklist) - Token size larger than session IDs - Clock sync required between services ## Alternatives Considered | Alternative | Why Rejected | |-------------|--------------| | Session cookies | Not API-friendly, CSRF issues | | OAuth2/OIDC | Overkill for simple auth | | PASETO | Less battle-tested | | opaque tokens | Requires DB lookup on every request | ## Implementation Notes - JWT library: PyJWT - Redis client: aioredis for async - Both tokens stored in HttpOnly cookies for browser clients - Access token in Authorization header for API clients