Add JWT_SECRET_NEXT env var support for seamless JWT secret rotation: - JwtStrategy: use secretOrKeyProvider to try primary then fallback key - TokenService.verifyAccessToken(): dual-key fallback for internal callers - Redis metric jwt_verify_with_next_total for monitoring cut-over progress - Session revocation marker support restored in JwtStrategy.validate() - Unit tests for all three verification scenarios (primary, fallback, both-fail) - docs/security/secret-rotation.md runbook with step-by-step rotation procedure Closes GOO-203. Co-Authored-By: Paperclip <noreply@paperclip.ing>
1.1 KiB
1.1 KiB
JWT Secret Rotation Runbook
Zero-downtime JWT secret rotation using dual-key verification.
Environment Variables
| Variable | Required | Description |
|---|---|---|
JWT_SECRET |
Yes | Primary signing and verification key |
JWT_SECRET_NEXT |
No | Fallback verification-only key during rotation |
How It Works
- Signing: Always uses
JWT_SECRET(primary). Tokens are never signed with_NEXT. - Verification: Tries
JWT_SECRETfirst. On failure, falls back toJWT_SECRET_NEXTif set. - Metric: Each fallback verification increments
metrics:jwt_verify_with_next_totalin Redis.
Rotation Procedure
- Generate new secret:
openssl rand -base64 48 - Deploy with
JWT_SECRET=<old>,JWT_SECRET_NEXT=<new> - Swap:
JWT_SECRET=<new>,JWT_SECRET_NEXT=<old> - Wait 15 minutes (access token TTL)
- Drop
JWT_SECRET_NEXT - Verify no 401 spikes
Rollback
Swap back: JWT_SECRET=<old>, JWT_SECRET_NEXT=<new>.
Emergency: Forced Re-login
Rotate to a new secret without setting _NEXT. All existing tokens become invalid.