Stop Random Logouts With an Explicit Session Cookie
Random logouts are usually an expiry or scope rule you never chose. A framework set a session cookie with a default lifetime, the browser rejected it on a cross-site request, or logout tried to clear a different cookie from the one login created.
Write the policy down. Every attribute should have a reason.
The session-cookie contract
For a production browser session, decide:
- Name: use a stable name and consider a
__Host-prefix when the topology allows it. - HttpOnly: prevents page JavaScript from reading the session cookie.
- Secure: sends it only over HTTPS.
- SameSite: choose
Lax,Strict, orNonefrom the actual cross-site flow.Nonealso requiresSecurein modern browsers. - Domain: omit it for a host-only cookie unless subdomains genuinely need to share it.
- Path: normally
/, and logout must use the same path. - Max-Age or Expires: make the session lifetime explicit.
- Refresh policy: decide when a valid session extends and when it absolutely ends.
Do not cargo-cult one snippet into every deployment. A same-site web app and API can use a tighter policy than an embedded or cross-site flow.
Why clearing a cookie can fail
Browsers identify a cookie by name plus its scope. If login set Domain=.example.com; Path=/ and
logout clears the same name with no domain or a different path, the original cookie remains.
Inspect the storage panel after logout instead of trusting a 200 response.
Also check the server clock and session-store expiry. A browser cookie valid for seven days does not help if the backing session row expires after one hour.
Fail visibly
The application should distinguish:
- missing session;
- expired session;
- invalid or revoked session;
- cookie rejected by browser policy;
- refresh failure.
Those states can share a safe user-facing message, but they should not collapse into one useless log entry. Record the reason without recording the session value.
Browser tests that catch the real bug
- login over production HTTPS and inspect
Set-Cookie; - refresh within and beyond the intended idle window;
- open the app through the actual frontend and API origins;
- test the cross-site case if one exists;
- log out and confirm the scoped cookie disappears;
- revoke the server session and confirm the cookie cannot restore it.
Claude can audit configuration and draft tests. Code must generate and validate the session, and logs must never print its raw value.
Run the starter locally
npm test
npm run validate
npm run sample
Dry-run validates a fictional cookie policy and returns an audit shape. Docker Compose and n8n are included, but the pack never creates a real session or changes browser settings.