fix: TRAC-814 Make session token cookies expire with the session#3047
fix: TRAC-814 Make session token cookies expire with the session#3047chanceaclark wants to merge 1 commit into
Conversation
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Bundle Size ReportComparing against baseline from No bundle size changes detected. |
2e5f839 to
832814b
Compare
Unlighthouse Performance Comparison — VercelComparing PR preview deployment Unlighthouse scores vs production Unlighthouse scores. Summary ScoreAggregate score across all categories as reported by Unlighthouse.
Category Scores
Core Web Vitals
|
832814b to
4347627
Compare
4347627 to
7a7e8db
Compare
authjs.session-token and authjs.anonymous-session-token must be session
cookies (no Expires attribute) to comply with Essential cookie
classification requirements.
- Remove maxAge from authjs.anonymous-session-token in anonymousSignIn
- Strip Expires from authjs.session-token in the withAuth middleware,
where Auth.js refreshes the JWT on every non-API request
- Strip Expires from authjs.session-token in the auth route handler,
where Auth.js sets the cookie on sign-in (not covered by middleware)
- Wrap signIn and updateSession in auth/index.ts with patchSessionTokenCookies,
which re-sets session token cookies via cookies().set() without Expires
after Auth.js sets them — this covers the server action code path where
Auth.js calls cookies().set(name, value, { expires: ... }) directly
Auth.js v5 unconditionally sets Expires on session cookies with no config
option to disable it. signIn/updateSession use the Next.js cookies() API
rather than response headers, so those must be intercepted separately.
Fixes TRAC-814
Co-Authored-By: Claude <noreply@anthropic.com>
7a7e8db to
df9d1f2
Compare
| // Auth.js always sets Expires on session cookies based on session.maxAge. We strip it here | ||
| // so the cookie becomes a session cookie (expires when the browser closes), which is required | ||
| // for Essential cookie classification compliance. |
There was a problem hiding this comment.
There's no scenario for a consent selection that won't expire the cookie on browser close?
There was a problem hiding this comment.
Yep, consent selection cookies are handled separately and aren't affected here. The stripSessionCookieExpiry function only modifies cookies that match SESSION_TOKEN_COOKIE_RE, which targets authjs.session-token specifically. Consent cookies have their own names and expiry, so they'll persist across browser sessions as expected.
Jira: TRAC-814
What/Why?
authjs.session-tokenandauthjs.anonymous-session-tokenmust be session cookies (noExpiresattribute) to comply with Essential cookie classification requirements.Anonymous session token: removed
maxAgefromanonymousSignIn— without it, Next.js omits theMax-Age/Expiresattribute and the cookie becomes a session cookie.Auth session token: Auth.js v5 unconditionally sets
Expireson the session cookie based onsession.maxAge— there is no config option to disable this. The fix post-processesSet-Cookieheaders to strip theExpiresattribute from matching cookies. This is applied in two places:proxies/with-auth.ts— covers session refreshes on every page request (the middleware matcher excludes/api/*)app/api/auth/[...nextauth]/route.ts— covers sign-in, where Auth.js sets the initial session cookie (not reachable by middleware)The regex matches
authjs.session-token,__Secure-authjs.session-token(HTTPS prefix), and chunked variants (authjs.session-token.0, etc.). OnlyExpiresis stripped —Max-Age=0(used by Auth.js for cookie deletion) is left intact.Testing
authjs.anonymous-session-tokenhas noExpirescolumn value (session cookie)authjs.session-tokenhas noExpirescolumn valueMigration
No migrations required.