Problem
Two authentication gaps exist:
- The logout endpoint in
src/modules/auth/auth.controller.ts returns a success response but takes no action - the issued JWT remains fully valid until it naturally expires, making logout functionally useless
.env.example defines REFRESH_TOKEN_SECRET and REFRESH_TOKEN_EXPIRES_IN but no refresh token is issued on login and no refresh endpoint exists
Proposed Solution
Token blacklist:
- On login, include a
jti (JWT ID) claim using uuid
- On logout, store the
jti in Redis with TTL equal to the token's remaining lifetime
- In
JwtAuthGuard, check Redis for the jti and reject blacklisted tokens with 401
Refresh token:
- On login, issue a long-lived refresh token stored as an httpOnly cookie
- Add
POST /api/auth/refresh that validates the refresh token and returns a new access token
- On logout, also invalidate the refresh token
Acceptance Criteria
Problem
Two authentication gaps exist:
src/modules/auth/auth.controller.tsreturns a success response but takes no action - the issued JWT remains fully valid until it naturally expires, making logout functionally useless.env.exampledefinesREFRESH_TOKEN_SECRETandREFRESH_TOKEN_EXPIRES_INbut no refresh token is issued on login and no refresh endpoint existsProposed Solution
Token blacklist:
jti(JWT ID) claim usinguuidjtiin Redis with TTL equal to the token's remaining lifetimeJwtAuthGuard, check Redis for thejtiand reject blacklisted tokens with 401Refresh token:
POST /api/auth/refreshthat validates the refresh token and returns a new access tokenAcceptance Criteria
POST /api/auth/refreshwith a valid refresh token returns a new access token