Skip to content

Commit d743430

Browse files
antharya05claude
andauthored
feat(auth): add JWT token revocation with Redis blocklist (#476)
* feat(auth): add JWT token revocation with Redis blocklist 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> * fix(lint): add explicit return types * extract OAuth helpers and improve logout logging --------- Signed-off-by: J.ANTHARYA <antharyajalligampala@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e243c8c commit d743430

6 files changed

Lines changed: 827 additions & 17 deletions

File tree

apps/backend/src/__tests__/app.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { describe, it, expect, vi } from 'vitest';
33
import { buildApp } from '../app';
44

55
process.env.NODE_ENV = 'test';
6-
process.env.JWT_SECRET ||= 'test-jwt-secret';
7-
process.env.ENCRYPTION_KEY ||= 'test-encryption-key';
6+
// validateEnv() runs inside buildApp() and exits if these are absent.
7+
// Provide safe test-only fallbacks so CI doesn't need real secrets here.
8+
process.env.JWT_SECRET ??= 'test-jwt-secret-not-for-production-xxxxxxxxxxxxxxxxxxxxxxx';
9+
process.env.ENCRYPTION_KEY ??= 'a'.repeat(64);
810

911
describe('GET /health', () => {
1012
it('should return status ok', async () => {

0 commit comments

Comments
 (0)