fix(auth): scope session cookies to registrable domain + diagnostic reasons - #840
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
tran-christian
marked this pull request as draft
April 22, 2026 02:22
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
…easons Session cookies stamped after exchangeCodeForSession are Host-only by default in @supabase/ssr 0.8. On Vercel the response host can be an internal LB, so Set-Cookie attaches to that host even though Location points at www.omshub.org — and the browser never sends the session back. #835 fixed the redirect target via x-forwarded-host but did not touch the cookie scope; the reporter confirmed in DevTools that the PKCE code_verifier lands while sb-<ref>-auth-token[.0/.1] does not. Explicitly set Domain to the registrable domain (omshub.org, derived from the public host with www. stripped) so the session is valid on both www and apex regardless of which host answered the request. Skipped for localhost / IP literals — Host-only is correct there and some browsers reject Domain=localhost. Also split the error redirect into four distinguishable ?reason= values (no_code, exchange_failed, no_session, no_pending_cookies) and add a 60-second non-HttpOnly auth_debug cookie on success so the next sign-in attempt is conclusive from DevTools alone — removeConsole: true strips server logs in prod.
tran-christian
force-pushed
the
claude/debug-pending-cookies-FNAlV
branch
from
April 22, 2026 02:48
5902e61 to
6f951fc
Compare
tran-christian
marked this pull request as ready for review
April 22, 2026 02:49
7 tasks
tran-christian
added a commit
that referenced
this pull request
Apr 22, 2026
…841) @supabase/ssr 0.8.0 has an SSR race condition where the GoTrue client auto-initializes asynchronously and can hijack the cookie-writing path after exchangeCodeForSession. The symptom in our setup: /token returns 200, data.session is populated, but the SSR client never invokes the cookies.setAll callback — so session cookies never reach the response. Our diagnostic patch (#840) surfaced this exact branch as ?reason=no_pending_cookies. Fixed upstream in 0.8.1 via skipAutoInitialize: true (PR #131). Bumping to latest 0.10.2 picks up that fix plus 0.10.0's setAll cache headers, which prevent proxies/CDNs from caching auth responses. @supabase/supabase-js bumped to ^2.104.0 to satisfy the new peer requirement (ssr 0.10.2 needs ^2.102.1). No breaking changes in either package in the traversed range — createServerClient, createBrowserClient, exchangeCodeForSession, getSession, getUser, onAuthStateChange all retain their signatures. No source changes — package.json + pnpm-lock.yaml only.
4 tasks
tran-christian
added a commit
that referenced
this pull request
Apr 22, 2026
…ug cookie (#842) With the root cause fixed in #841, the browser-side auth_debug cookie from #840 has served its purpose — it was one-off scaffolding to prove the pipeline carries cookies end-to-end. Replacing it with server-side error logs in Vercel's runtime log viewer: zero client footprint, no leaked deployment details to analytics/replay scripts, full context when things actually go wrong. next.config.js: removeConsole in prod now uses { exclude: ['error'] } so console.error survives compilation. console.log/warn/info/debug are still stripped. DEBUG_AUTH=1 continues to disable stripping entirely for local `pnpm build && pnpm start` repro. app/auth/callback/route.ts: - Shared `diag` object captures the same fields the auth_debug cookie carried (forwardedHost, pendingCookieCount, pendingCookieNames, requestCookieNames, publishableKeyPrefix, origin, hasSession, hasUser) plus SDK-side signals. - Every abnormal branch logs `[auth/callback] reason=<branch>` with `diag` to console.error. exchange_failed also includes the SDK message + status. no_code is not logged (crawler noise). - auth_debug cookie + debugPayload construction removed. - DEBUG_AUTH-gated console.log block removed — its content is a subset of `diag` and only fires now when something is actually wrong. - Unused `oauth_error` option removed from failureRedirect's union.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fifth attempt at the OAuth session-cookie bug. Builds on #835's
x-forwarded-hostredirect fix with the one thing it didn't touch: cookie scope. Plus adds conclusive diagnostics so the next failing attempt (if any) pinpoints the branch without needing server logs —removeConsole: truestrips them.Root cause hypothesis
PR #835's author confirmed in DevTools on
www.omshub.orgthat the PKCE-code-verifiercookie lands butsb-<ref>-auth-token[.0/.1]do not, despite Supabase returning/token 200.x-forwarded-hostcorrects the redirect target, but theSet-Cookieresponse is still emitted by whichever host answered the function invocation — on Vercel that can be an internal LB.@supabase/ssr0.8 writes cookies with noDomainattribute, so they become Host-only and bind to that internal host. The browser then navigates towww.omshub.organd never sends them.What changed
app/auth/callback/route.ts:Domainderived fromx-forwarded-host(falling back toorigin), with port and leadingwww.stripped — e.g.Domain=omshub.org. Session stays valid on bothwww.omshub.organd the bare apex regardless of which host the response came from.localhost/ IP literals are skipped (some browsers rejectDomain=localhost; Host-only is correct for local dev)./?error=auth_callback_error&reason=<one of: no_code | exchange_failed | no_session | no_pending_cookies>(with a truncatedmessage=for exchange errors). Makes prior "something failed" silence legible.auth_debugcookie on success (60s, non-HttpOnly) encoding{ host, usedForwardedHost, cookieDomain, pendingCookieCount }. If this cookie is missing in DevTools → Cookies →omshub.orgafter sign-in, we know the whole response was rejected; if it's present butsb-*-auth-token*aren't, the bug is inside@supabase/ssritself.failureRedirect,clearVerifierAndReturn) to dedupe the error paths.app/page.tsx+app/_components/AuthErrorNotification.tsx:reasonandmessagesearch params into the Mantine error toast so they surface in the UI, not just the URL.Why prior attempts didn't land
/auth/callbackproxy exclusion (PKCE fix). Correct, kept.response.cookies.set()/headers.append('Set-Cookie', …). Correct shape but cookies still Host-only.x-forwarded-hostfor redirect target. Correct, kept. Addresses where the browser lands, not what host cookies are bound to.Domain scoping is the last piece. If after this deploy the session still doesn't stick, the
auth_debugcookie +reason=param tell you exactly which of the four remaining failure modes to investigate without digging through Vercel logs.Test plan
www.omshub.orgwith Google → lands on/with session (welcome toast), no?error=omshub.org:auth_debugpresent,sb-<ref>-auth-token(+ chunks.0/.1if large) present withDomain=omshub.orgomshub.orgin a new tab — still signed in (proves the scope widening)?error=;auth_debughascookieDomain: "<preview>.vercel.app"pnpm dev) sign-in via magic link still works (Host-only path)src/lib/supabase/__tests__/proxy.test.ts) still passes/auth/callbackdirectly in a browser — lands on/?error=auth_callback_error&reason=no_codewith matching toastRollback
Revert the commit — all changes are additive to
app/auth/callback/route.ts,app/page.tsx, andapp/_components/AuthErrorNotification.tsx. No schema, config, or env var changes.