Fix logout not clearing prefixed NextAuth cookies over HTTPS #220

Merged
aaperis merged 1 commit from bugfix/clear-sucure-cookies into develop 2026-09-14 09:22:10 +00:00
aaperis commented 2026-09-11 14:57:55 +00:00 (Migrated from github.com)

Follow-up fix to #199 .

Problem

When the app runs over HTTPS, pressing Logout does not clear the nextauth session from the browser. Over HTTP (dev), the same code worked correctly because they are not attributed as secure.

Root cause

cookies().delete(name) emits Set-Cookie: <name>=; Max-Age=0; Path=/ without the Secure attribute. Browsers reject any Set-Cookie for a __Host- or __Secure- prefixed cookie that isn't marked Secure - including deletion headers. The deletion is silently dropped and the cookie stays.

The same bug affected updateServerToken's fail-closed branch (when access-token verification proves the session is invalid): the cookie wasn't actually being cleared in HTTPS environments.

Fix implemented

Replace store.delete(name) in serverToken.ts with an explicit expired store.set(...) that carries Secure for prefixed cookie names, so the browser accepts the deletion.

Changes:

  • New internal expireCookie helper that writes an expired cookie with the correct attributes (Secure when the name is prefixed, Path=/, HttpOnly, SameSite=Lax, Max-Age=0).
  • clearServerToken and the fail-closed branch of updateServerToken now use expireCookie instead of store.delete.
  • Tests updated to assert on store.set(name, "", { maxAge: 0, secure: true, ... }) for prefixed names, and maxAge: 0 (without requiring secure) for non-prefixed names.

Testing

  • Steps to verify the fix after the change

The bugfix is deployed on the demo site. Go there to test:

  • Manual: log in over HTTPS, log out, confirm all three cookies are gone in DevTools.
  • Unit tests updated and passing.
Follow-up fix to #199 . ## Problem When the app runs over HTTPS, pressing **Logout** does not clear the nextauth session from the browser. Over HTTP (dev), the same code worked correctly because they are not attributed as secure. ## Root cause `cookies().delete(name)` emits `Set-Cookie: <name>=; Max-Age=0; Path=/` **without** the `Secure` attribute. Browsers reject any `Set-Cookie` for a `__Host-` or `__Secure-` prefixed cookie that isn't marked `Secure` - including deletion headers. The deletion is silently dropped and the cookie stays. The same bug affected `updateServerToken`'s fail-closed branch (when access-token verification proves the session is invalid): the cookie wasn't actually being cleared in HTTPS environments. ## Fix implemented Replace `store.delete(name)` in `serverToken.ts` with an explicit expired `store.set(...)` that carries `Secure` for prefixed cookie names, so the browser accepts the deletion. Changes: - New internal `expireCookie` helper that writes an expired cookie with the correct attributes (`Secure` when the name is prefixed, `Path=/`, `HttpOnly`, `SameSite=Lax`, `Max-Age=0`). - `clearServerToken` and the fail-closed branch of `updateServerToken` now use `expireCookie` instead of `store.delete`. - Tests updated to assert on `store.set(name, "", { maxAge: 0, secure: true, ... })` for prefixed names, and `maxAge: 0` (without requiring `secure`) for non-prefixed names. ## Testing - Steps to verify the fix after the change The bugfix is deployed on the demo site. Go there to test: - Manual: log in over HTTPS, log out, confirm all three cookies are gone in DevTools. - Unit tests updated and passing.
HenrikeW commented 2026-09-14 09:02:12 +00:00 (Migrated from github.com)

I'll start a review...

I'll start a review...
HenrikeW (Migrated from github.com) approved these changes 2026-09-14 09:21:11 +00:00
HenrikeW (Migrated from github.com) left a comment

This looks good to me, I've tested it on the demo site and seen it working. 💯

This looks good to me, I've tested it on the demo site and seen it working. :100:
Sign in to join this conversation.
No description provided.