Skip to content

fix: forward every set-cookie header on logout - #103

Closed
mroderick wants to merge 4 commits into
mainfrom
test/cookie-attributes
Closed

mroderick wants to merge 4 commits into
mainfrom
test/cookie-attributes

Conversation

@mroderick

@mroderick mroderick commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Logout cleared only one of the three Better Auth cookies. forwardCookies called c.header("Set-Cookie", cookie) once per cookie, and Hono keeps only the last value of a repeated header, so the three clearing cookies from signOut collapsed into better-auth.dont_remember. The browser kept session_token and session_data. The helper now passes { append: true }.

The PR also adds test/integration/cookie-attributes.test.js, which covers the cookie path that had no tests: the session cookie's attributes on magic-link verification, the authorize endpoint setting no cookie, and logout forwarding all three clearing cookies with their attributes. That coverage is the baseline the dependency review of #102 was blocked on.

Review notes

Focus on the one-line production change in src/app/utils/cookies.js. The risk to check is whether appending can duplicate a Set-Cookie that something else on the response already emitted. forwardCookies has one caller, src/app/handlers/logout.js, which forwards headers from auth.api.signOut before returning c.redirect, so nothing else sets them on that response. The new test asserts that exactly three cookies arrive.

An earlier draft of these tests assumed a better-auth.state cookie exists on /oauth2/authorize. It does not: with the seeded planner client, every authorize path answers with a redirect and no cookie, because OAuth state travels in a signed query string. That test is replaced by one that pins the real contract.

forwardCookies called c.header once per cookie. Hono keeps only the last
value of a repeated header, so the three clearing cookies from signOut
collapsed into better-auth.dont_remember and the browser kept the stale
session cookies.

Pass append: true so each Set-Cookie survives as its own header. The new
integration test asserts that all three arrive with Max-Age=0, Path=/,
HttpOnly and SameSite=Lax.
readSetCookie returned only the first Set-Cookie entry when headers
arrived in array shape, and magicLinkHeaders returned an undefined
headers object that surfaced later as a generic assertion failure.
Both are test-only diagnostics.
@mroderick
mroderick marked this pull request as ready for review November 11, 2026 16:30
@mroderick
mroderick added this pull request to stack #106 November 11, 2026 16:31
@till

till commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator

There's no code in better-auth itself to do this? Or constants to re-use?

olleolleolle
olleolleolle previously approved these changes Nov 11, 2026

@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.

⭐ Thanks!

logout copied Set-Cookie values from a Headers object onto the Hono
context through a hand-rolled helper. Hono's c.header replaces rather
than appends, which is how two of the three clearing cookies were
dropped before #103.

Ask 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. forwardCookies and its module are gone.
asResponse makes better-auth return APIErrors as error responses
instead of throwing them (dispatch.mjs:193,249,258). logout never read
the status, so a failed signOut redirected to /?message=Bye! while the
session still stood.

Return the signOut response and log the status when it is not ok.
@mroderick mroderick closed this Nov 12, 2026
mroderick added a commit that referenced this pull request Nov 12, 2026
logout copied Set-Cookie values from a Headers object onto the Hono
context through a hand-rolled helper. Hono's c.header replaces rather
than appends, which is how two of the three clearing cookies were
dropped before #103.

Ask 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. forwardCookies and its module are gone.
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.

3 participants