Skip to content

fix(session): align auth cookie maxAge with Redis session TTL#3870

Open
hariom888 wants to merge 1 commit into
Premshaw23:masterfrom
hariom888:fix/session-cookie-redis-ttl-mismatch
Open

fix(session): align auth cookie maxAge with Redis session TTL#3870
hariom888 wants to merge 1 commit into
Premshaw23:masterfrom
hariom888:fix/session-cookie-redis-ttl-mismatch

Conversation

@hariom888

Copy link
Copy Markdown

Problem

getAuthCookieOptions() in app/api/auth/session/route.js set maxAge: 60 * 60 (1 hour) for both the authToken and sessionId cookies. createSession() in lib/sessionManager.js persisted the session in Redis with ex: 24 * 60 * 60 (24 hours), and the user:sessions:{userId} set was also expired after 24 hours. The two lifetimes were set independently with no shared constant, so they had drifted (1h vs 24h).

Consequences:

  • After 1h, the browser drops both cookies — the client appears logged out and has no sessionId cookie left to call
    DELETE /api/auth/session and cleanly terminate the session.
  • The Redis session:{sessionId} entry stays valid for up to 23 more hours, showing up as a "ghost" active session in admin tooling (app/api/admin/sessions/terminate/route.js) that the legitimate user can no longer terminate themselves, and which occupies the single-session slot enforced by createSession's termination logic on the user's next real login.

Fix

Extract a single shared constant, SESSION_TTL_SECONDS, in lib/sessionConstants.js, and use it for both:

  • the cookie maxAge in getAuthCookieOptions()
  • the Redis TTL (ex/expire) in createSession()

The cookie lifetime was raised to match the 24h Redis TTL (rather than shrinking the Redis TTL to 1h), since the single-session-per-user guarantee is meant to hold for the session's full real lifetime. The logout path's cookie-clearing (maxAge: 0) is unaffected.

Tests

  • lib/__tests__/sessionTtlConsistency.test.js: asserts the TTL createSession passes to Redis equals SESSION_TTL_SECONDS — the exact "fails CI if they drift" guard requested in the issue.
  • app/api/auth/session/__tests__/route.test.js: asserts both the authToken and sessionId cookies set by POST /api/auth/session have maxAge === SESSION_TTL_SECONDS (and explicitly not the old 60 * 60).

Closes #3805

getAuthCookieOptions() set maxAge: 60 * 60 (1h) for the authToken and sessionId cookies, while createSession() persisted the Redis session with ex: 24 * 60 * 60 (24h). The two had drifted because they were set independently with no shared constant.

After 1h the browser dropped the cookies (client appears logged out, can no longer call DELETE /api/auth/session since there's no sessionId cookie left to send), while the Redis session remained valid and visible to admin tooling for up to 23 more hours, consuming the single-session slot enforced by createSession on the user's next real login. Extract SESSION_TTL_SECONDS into lib/sessionConstants.js and use it for both the cookie maxAge and the Redis TTL, so they can't drift apart again.

Add a regression test asserting the TTL passed to Redis equals the cookie's maxAge, and a route-level test asserting both cookies use SESSION_TTL_SECONDS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] : Auth cookie maxAge (1h) and Redis session TTL (24h) mismatch leaves orphaned active sessions

1 participant