Safety
Cookie Max-Age vs Session Cookies for Login Lifetime
August 19, 2022
Cookie Max-Age vs session cookies is how long the browser is asked to keep the cookie, not how well it is locked: omit Max-Age and Expires for a session cookie, or set Max-Age in seconds when you want a clock, knowing Chromium session restore can still revive a 'session' cookie after a restart. Auth cookies still need Secure, HttpOnly, and SameSite on the name that proves login. RoastMyOpsec grades those three flags on session-like Set-Cookie names on the landing response and does not fail a site for Max-Age versus a session cookie.
The practical difference
A session cookie is a Set-Cookie with no Max-Age and no Expires. The user agent keeps it until it considers the browsing session over. That is a browser policy, not a server-enforced logout, and session restore can make the cookie outlive 'I quit the app.'
Max-Age is a delta in seconds from when the cookie is stored. Expires is an absolute date. If both are present, Max-Age wins. Zero or negative Max-Age is how you delete a cookie you already set, matching name, Path, and Domain. Neither attribute replaces HttpOnly, Secure, or SameSite, and neither stops a stolen cookie from working until the server session is revoked.
How to choose based on what you shipped
Pick lifetime from the product, then lock the cookie. Short-lived auth with refresh (minutes to a day of Max-Age) fits most public logins. A session cookie fits 'stay signed in only while this browser is open' — if you accept restore. Preference cookies can live longer; they should not be the login.
Do not use a year-long Max-Age on a session-shaped name to skip logout design. Server-side expiry and rotation still matter. Prefixes (__Host- / __Secure-) and Path=/ are separate contracts.
| Option | When it wins | Watch-out | Takeaway |
|---|---|---|---|
| Session cookie (no Max-Age/Expires) | You want the jar empty after a real browser quit | Session restore can keep it; not a security flag | Fine for 'this sitting' if the server still expires sessions |
| Max-Age in seconds | You want a known clock and easier clock-skew behavior than Expires | Huge Max-Age is a stolen-cookie window, not a feature | Default for new auth cookies with refresh |
| Expires date | Legacy stacks that only speak Expires | Server/client clock skew; Max-Age overrides it if both are set | Prefer Max-Age when you can |
| Max-Age=0 on logout | You must drop this name now | Path/Domain mismatch leaves a twin cookie alive | Match the original setter; still revoke the server session |
When a session cookie still wins
A session cookie still wins on a kiosk-style or shared-device flow where you do not want a calendar reminder sitting in the jar after quit — as long as you also expire the server session and you accept restore. It does not win as a substitute for HttpOnly on an XSS-prone marketing origin.
Persistent Max-Age wins when users expect to come back tomorrow without a full login, or when you rotate refresh tokens on a clock. Keep the lifetime honest in your privacy copy. A public roast of the homepage often never sees the login Set-Cookie at all.
Common mistakes
The first mistake is treating a session cookie as automatically safer than Max-Age.
The second mistake is a 400-day auth Max-Age because the browser cap exists, not because the account should live that long in the jar.
The third mistake is deleting with Max-Age=0 on Path=/ while the original cookie was Path=/app.
What a URL roast can prove
Paste a URL you own into RoastMyOpsec for a free read of landing headers, HTTPS scheme, session-like cookie flags, sensitive paths, and public JavaScript secrets. Cookie grading is Secure, HttpOnly, and SameSite on names that look like session, auth, token, jwt, or sid — not Max-Age versus session as a standalone F, not cookie Priority, and not a login walkthrough. No Set-Cookie on the homepage is an info result, not a pass on logout hygiene. The scan does not score GPC, does not submit HSTS preload, and does not run exploit payloads.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Is a session cookie more secure than Max-Age?
- No. Lifetime and flags are different jobs. Session cookies can persist across restore. Set Secure, HttpOnly, and SameSite either way, and expire the server session on logout.
- Does RoastMyOpsec fail missing Max-Age on auth cookies?
- No. Max-Age versus a session cookie is not a standalone fail. The free cookie check looks for Secure, HttpOnly, and SameSite on session-like names on the audited response.
- Should login cookies use Max-Age or stay session cookies?
- Use Max-Age when you want a known lifetime and refresh. Use a session cookie when you truly want browser-session semantics and accept restore. Do not pick either to skip HttpOnly.