feat: support browser-session cookies for the session token cookie #13457
Replies: 1 comment
-
|
For more concrete context on why this matters: here's the workaround we need/had to ship in Catalyst (BigCommerce's Next.js storefront) to satisfy an Essential cookie classification compliance requirement: bigcommerce/catalyst#3047 The PR ends up patching the cookie in three separate places:
export const signIn = async (...args: Parameters<typeof authSignIn>) => {
try {
return await authSignIn(...args);
} finally {
await patchSessionTokenCookies();
}
};The regex itself has to account for the This is exactly the kind of thing that should be a single config option rather than a multi-site interception hack. Any Auth.js upgrade that changes cookie names, the write path, or the order of operations silently breaks this. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Context
There's a class of apps — particularly those with strict GDPR compliance requirements — that need the session-token cookie to be a browser-session cookie (no
Expires/Max-Age).Under GDPR and the ePrivacy Directive, strictly necessary cookies are exempt from consent requirements. Authentication cookies typically qualify. However, compliance teams and some European DPAs expect "strictly necessary" to also mean minimally scoped — and a persistent cookie with a 30-day
Expiresattribute is harder to defend as "strictly necessary" than one that disappears when the browser closes. The data minimization principle (Article 5(1)(c)) pushes in the same direction: don't retain longer than needed, and a browser session is often the right scope for an auth token.This also comes up outside of GDPR — banking and government applications commonly prohibit persistent auth cookies by policy, and enterprise SSO setups sometimes require the auth cookie lifetime to be session-scoped even when the underlying token has a longer validity window.
Right now there's no first-class way to get this behavior from Auth.js. Apps that need it have to strip
Expires/Max-Ageout of theSet-Cookieheader after Auth.js writes it. That means intercepting in middleware, in route handlers, and aroundsignIn/updateSession— which write cookies via the framework'scookies()API rather than response headers, so they need a separate interception path. It's fragile, it depends on internal cookie names, and it breaks silently across upgrades.Prior art
This has come up a few times before without resolution:
session.maxAge, went stale and was closed.session.maxAgetoundefined. Closed without implementation.Two reasonable places to put the config knob
Option A:
session.maxAge: nullThe problem here is that
session.maxAgedrives two separate things: the cookie'sExpiresattribute and the JWTexpclaim (or the DB session expiry column). There's no such thing as a "session-scoped JWT" —jose'sEncryptJWTrequires anexpclaim. Sonullwould need to mean "no cookie expiry, but still use some fallback forexp", which conflates two concerns in one option. It's a little muddy.Option B:
cookies.sessionToken.options.maxAge: null(I think this is the right call)This keeps the concerns separate.
session.maxAgekeeps controlling JWTexpand DB session expiry unchanged. The cookie config controls the cookie transport layer. SettingmaxAge: nullon the session token cookie means "omitExpiresandMax-Age" — the existingcookiesconfig already lets you customize the session token cookie, this just addsnullas a valid value to signal a browser-session cookie.The caveats worth documenting:
session.maxAgestill enforces expiry via JWTexp(default 30 days). The session will become invalid after that window even if the browser never closed. That's actually correct behavior — it's the enforcement layer.expirescolumn is unaffected. The DB row still expires aftersession.maxAge. The cookie just becomes session-scoped.I've got a PoC branch implementing Option B if it'd be useful as a reference: https://github.com/chanceaclark/next-auth/tree/feat/session-cookie-maxage-null
Happy to open a PR against this once y'all weigh in on the API surface. Totally open to a different shape if there's a better place for it.
Beta Was this translation helpful? Give feedback.
All reactions