feat(auth): add JWT token revocation with Redis blocklist#476
Open
antharya05 wants to merge 1 commit into
Open
feat(auth): add JWT token revocation with Redis blocklist#476antharya05 wants to merge 1 commit into
antharya05 wants to merge 1 commit into
Conversation
Adds secure logout that revokes the current JWT by storing a hash of its
signature in Redis with a TTL equal to the token's remaining lifetime.
The entry self-cleans when the JWT naturally expires, keeping Redis lean.
Changes:
- utils/jwt.ts: extractRawJwt() and blocklistKey(SHA-256(sig)) utilities
- app.ts: authenticate decorator checks Redis blocklist before jwtVerify;
registers @fastify/cookie before @fastify/jwt so cookie-based
auth works for web browser clients (was silently broken before)
- routes/auth.ts: DELETE /auth/logout endpoint (requires valid JWT);
POST /auth/logout simplified to cookie-clear only (backward compat)
- logout.test.ts: 36 tests covering revocation flow, cookie auth, Redis failures,
edge cases, and end-to-end invariants
- app.test.ts: set JWT_SECRET/ENCRYPTION_KEY fallbacks so CI can call buildApp()
- package.json: add typecheck script consumed by CI workflow
- ciScript.js: fix path generation — test files in __tests__/ were being
double-suffixed (logout.test.ts -> logout.test.test.ts)
Security decisions documented inline:
- Fail-open on Redis outage (acceptable for a portfolio app; JWT expiry is backup)
- SHA-256 hash of signature as blocklist key (claims never stored in Redis)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@antharya05 is attempting to deploy a commit to the Prashantkumar Khatri's projects Team on Vercel. A member of the Team first needs to authorize it. |
CI — Checks FailedBackend — FAIL
Mobile — SKIP
Web — SKIP
Last updated: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements secure JWT session invalidation using a Redis-backed blocklist.
Previously, JWTs remained valid until expiration even after logout, meaning a stolen token could continue accessing protected APIs after a user logged out. This change introduces server-side token revocation so tokens are immediately invalidated after logout while maintaining backward compatibility with existing logout flows.
Closes #306
Type of Change
What Changed
Added shared JWT utilities in
src/utils/jwt.ts:extractRawJwt()to consistently extract tokens from Authorization headers or cookiesblocklistKey()to generate SHA-256 hashed Redis blocklist keysExtended the global authentication decorator in
app.ts:jwtVerify()@fastify/cookiebefore@fastify/jwtso cookie-based authentication works correctly for browser clientsAdded authenticated
DELETE /auth/logoutendpoint:Simplified legacy
POST /auth/logout:Added comprehensive logout test coverage:
How to Test
Generate a JWT using an authenticated flow and access a protected endpoint.
Revoke the token:
Expected result:
401 UnauthorizedExpected result:
Checklist
Additional Context
Security decisions:
POST /auth/logoutno longer writes unverified tokens to Redis, preventing abuse of the logout endpoint.Repository note:
While validating this feature, I compared the latest
mainbranch against this branch.Existing failures in
event.test.tsandteam.test.tsoccur identically onmainand were not introduced by this authentication change.This PR introduces no additional test regressions.