Skip to content

fix(auth): stamp session cookies onto redirect response after OAuth exchange - #833

Merged
tran-christian merged 1 commit into
mainfrom
fix/auth-callback-cookies
Apr 16, 2026
Merged

fix(auth): stamp session cookies onto redirect response after OAuth exchange#833
tran-christian merged 1 commit into
mainfrom
fix/auth-callback-cookies

Conversation

@tran-christian

Copy link
Copy Markdown
Contributor

Summary

  • Root cause: Next.js does not propagate cookies() mutations into NextResponse.redirect() — session tokens were never delivered to the browser despite Supabase returning a valid token, so OAuth and magic-link logins silently failed
  • Fix: Buffer cookies in a pendingCookies[] array during setAll(), then explicitly stamp each one onto the NextResponse.redirect() response object before returning
  • Security: Guard the next param against //host open-redirect bypass; use plain origin (from new URL(request.url)) for all redirects — avoids cross-origin cookie mismatches on preview deployments that would occur with NEXT_PUBLIC_SITE_URL, and avoids the open-redirect risk of trusting x-forwarded-host
  • LoginDrawer: await the signInWithProvider call so errors surface via the existing notifyError toast instead of being swallowed

Test plan

  • Click "Continue with Google" → completes OAuth flow → lands on homepage signed in
  • Click "Continue with GitHub" → completes OAuth flow → lands on homepage signed in
  • Send magic link → click link in email → lands on homepage signed in
  • Send magic link → enter OTP code → signs in without page navigation
  • OAuth failure (revoke app access mid-flow) → redirected to /?error=auth_callback_error
  • Malformed next param (//evil.com) → redirected to / not external host
  • Preview deployment OAuth → session persists (cookies written to same origin as redirect)

…xchange

Next.js does not propagate cookies() mutations into NextResponse.redirect()
automatically — the Set-Cookie headers were missing, so the browser never
received session cookies despite Supabase confirming a successful login.

Root cause confirmed via Supabase auth logs: /token returned 200 (login)
on every Google OAuth and magic-link attempt, but users remained signed out.

Changes:
- Collect cookies in pendingCookies[] during setAll(), then explicitly stamp
  them onto the NextResponse.redirect() before returning
- Reject //host double-slash bypass in `next` param open-redirect guard
- Move cookieStore await after the oauthError early-return (avoid unnecessary work)
- Log exchangeCodeForSession errors for production debugging
- Replace filter/forEach with for..of to avoid intermediate array allocation
- Await signInWithProvider() in LoginDrawer so errors surface via notifyError
  toast instead of being silently swallowed
@vercel

vercel Bot commented Apr 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website Ready Ready Preview, Comment Apr 16, 2026 1:01pm

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant