All Stories
4-1-jwt-authentication-setupDoneEpic 4.1
Story 4.1: JWT Authentication Setup
Status: done
Tasks
- Task 1: Generate RSA Keypair (AC: 1)
- 1.1 Generate RSA 2048-bit private key using OpenSSL - Instructions in jwt_config.py
- 1.2 Extract public key from private key - Instructions in jwt_config.py
- 1.3 Document key generation in runbook - `generate_keypair_instructions()` function
- 1.4 Add keys to `.gitignore` - *.pem already in gitignore
- Task 2: Secure Key Storage (AC: 2, 10)
- 2.1 Create `server/app/core/jwt_config.py` configuration module
- 2.2 Add `JWT_PRIVATE_KEY` and `JWT_PUBLIC_KEY` environment variables
- 2.4 Implement key loading with proper error handling (log warning, fallback to HS256)
- 2.5 Add fallback to file-based keys for local development
- Task 3: RS256 Token Generation (AC: 3, 4, 6)
- 3.1 Update `create_access_token()` to use RS256 and private key
- 3.2 Add `iat` (issued at) timestamp to token payload
- 3.3 Add `iss` (issuer) = "wagerbabe.com" to token payload
- 3.4 Add `aud` (audience) = "wagerbabe-api" to token payload
- 3.5 Reduce ACCESS_TOKEN_EXPIRE_HOURS from 24 to 1
- 3.6 Update `create_refresh_token()` to use RS256
- Task 4: RS256 Token Validation (AC: 5)
- 4.1 Create `verify_token()` function using public key only
- 4.2 Validate `aud` claim matches "wagerbabe-api"
- 4.3 Validate `iss` claim matches "wagerbabe.com"
- 4.4 Handle `ExpiredSignatureError` with proper error tuple
- 4.5 Handle `InvalidTokenError` with proper error tuple
- Task 5: Migration Support (AC: 7, 8)
- 5.1 Create `verify_token_hybrid()` function supporting both algorithms
- 5.2 Try RS256 validation first, fall back to HS256 on failure
- 5.3 Log deprecation warning when HS256 token validated
- 5.4 Add `MIGRATION_END_DATE` constant (30 days from deploy: 2026-01-08)
- 5.5 After migration period, reject HS256 tokens with clear error
- Task 6: Update Auth Dependencies (AC: 3, 5, 7)
- 6.1 Update `get_current_user()` to use new validation
- 6.2 Update `get_current_agent()` - uses get_current_user dependency
- 6.3 Update `get_current_user_ws()` for WebSocket auth
- 6.4 Update refresh token endpoint to use hybrid validation
- 6.5 Add GET /auth/jwt/config endpoint for debugging
- Task 7: Testing (AC: 9)
- 7.1 Test RS256 token generation with valid payload
- 7.2 Test RS256 token validation with public key
- 7.3 Test expired RS256 token rejection
- 7.4 Test invalid RS256 token rejection
- 7.5 Test hybrid validation (RS256 first, HS256 fallback)
- 7.6 Test HS256 deprecation warning logging
- 7.7 Test token includes user data
- 7.8 23 unit tests passing
- 8.1 Update CLAUDE.md with new JWT configuration - Deferred
- 8.2 Key generation instructions in jwt_config.py
- 8.3 Migration timeline documented (MIGRATION_END_DATE constant)
Progress
Tasks7/7
Acceptance Criteria0
Total Tasks7