Skip to content

fix: forward every clearing cookie on logout - #108

Open
mroderick wants to merge 2 commits into
mainfrom
fix/logout-set-cookie
Open

mroderick wants to merge 2 commits into
mainfrom
fix/logout-set-cookie

Conversation

@mroderick

@mroderick mroderick commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Logout was clearing only one of the three better-auth cookies, so a session survived logout. This branch carries the fix that #103 and #107 built between them and never reached main, plus the GET-verb coverage salvaged from #104.

Hono's c.header("Set-Cookie", ...) replaces rather than appends, which is how the hand-rolled forwardCookies helper lost the second and third clearing cookie. The handler now asks better-auth for the signOut response itself with asResponse: true and appends its set-cookie values to the redirect Response. forwardCookies and src/app/utils/cookies.js are gone, AGENTS.md no longer lists a cookies utility, and no cookie name appears in the handler: what gets cleared is whatever signOut returns.

Review notes

Look at the error path first. It is the only behaviour change. asResponse: true makes better-auth return APIErrors as error responses instead of throwing them (node_modules/better-auth/dist/api/dispatch.mjs:193,249,258). Without a status check, a failed sign-out would redirect to /?message=Bye! while the session still stood. The handler returns the failure and logs the status instead, and a test injects a signOut that answers 500.

Two things this branch deliberately does not change:

  • /logout keeps its GET verb, which src/app/routes/auth.js already registers before this diff. The added GET test pins existing behaviour; whether session clearing should answer GET at all is a separate decision.
  • A thrown, non-APIError failure from signOut still escapes to Hono's default 500. The previous handler threw in the same case, and what a failed logout should answer is not decided anywhere in the app.

Also deliberately not done: no better-auth helper wraps this direction. applySetCookies and setCookieToHeader both write a request cookie header (applySetCookies ends in target.set("cookie", ...)), so the append happens on the Response directly.

One test-helper change rides along: the magic-link header handling moved into a single exported helper in test/helpers/test-instance.js. The new cookie-attribute test needs the raw response headers, the existing helper only returned the cookie, and copying its Better Auth header-shape workaround would have left two copies to drift.

Logout answers with these three headers
better-auth.session_token=; Max-Age=0; Path=/; HttpOnly; SameSite=Lax
better-auth.session_data=; Max-Age=0; Path=/; HttpOnly; SameSite=Lax
better-auth.dont_remember=; Max-Age=0; Path=/; HttpOnly; SameSite=Lax

The integration tests cover magic-link session cookie attributes, authorize setting no cookie, POST and GET /logout clearing all three cookies with their attributes, and a failed sign-out propagating its status.

Supersedes #103 (closed) and #107 (merged into #103's branch, not main); closes #104, whose other two tests targeted code this branch deletes.

Logout cleared only one of the three better-auth cookies, so a session
survived logout. The handler copied set-cookie values from a Headers
object onto the Hono context through a hand-rolled forwardCookies
helper, and Hono's c.header replaces rather than appends.

Ask better-auth for the signOut response itself with asResponse: true
and append its set-cookie values to the redirect Response. No code in
this repo then decides how cookies are forwarded, so a future handler
cannot lose headers the same way, and no cookie name appears locally.

asResponse makes better-auth return APIErrors as error responses
instead of throwing them (dispatch.mjs:193,249,258), so the status is
now checked. Without that check a failed sign-out redirected to
/?message=Bye! while the session still stood.

forwardCookies and src/app/utils/cookies.js are gone; AGENTS.md lists
the remaining utilities.
Pin the security attributes of the session cookie set by
magicLinkVerify, and that the authorize endpoint sets no cookie.

The magic-link header handling was duplicated between getAuthHeaders and
the new test, including the workaround for Better Auth returning either a
Headers object or an array of pairs. One exported helper now carries it
for both.
@mroderick
mroderick force-pushed the fix/logout-set-cookie branch from 5e8f04f to e7dd33d Compare November 12, 2026 08:18
@mroderick
mroderick marked this pull request as ready for review November 12, 2026 09:14

@olleolleolle olleolleolle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good test descriptions!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants