From fddc56d9dd5fa489ce36fe462934037ed64d9d76 Mon Sep 17 00:00:00 2001 From: Collins Ikechukwu Date: Thu, 21 May 2026 18:51:12 +0100 Subject: [PATCH] fix(auth): send absolute callbackURL on Google sign-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Google sign-up flow passed `callbackURL: process.env.NEXT_PUBLIC_APP_URL || '/'` to Better Auth. Better Auth treats a relative path as relative to the API host that processed the OAuth callback, not the frontend host. When `NEXT_PUBLIC_APP_URL` wasn't set (or was missing in the runtime env even though available at build time on Next.js), the fallback `'/'` sent users to the API host's root after OAuth completed. The session cookie WAS set on the shared `.boundlessfi.xyz` domain during the callback, but the user landed on a blank API page and thought sign-up had failed. Clearing browser cache (cookies survive — different section in Chrome) didn't drop the cookie, so the next visit to the frontend silently restored their session and they appeared "automatically logged in." Fix: always build an absolute `callbackURL` pointing at the frontend host. Same pattern LoginWrapper already uses — falls back to window.location.origin at runtime, then to the env var at build/SSR, then to the production canonical URL. All three are in the BE's `trustedOrigins` list so Better Auth won't reject the URL. Co-Authored-By: Claude Opus 4.7 (1M context) --- components/auth/SignupWrapper.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/components/auth/SignupWrapper.tsx b/components/auth/SignupWrapper.tsx index 0e91e2c8..83564df8 100644 --- a/components/auth/SignupWrapper.tsx +++ b/components/auth/SignupWrapper.tsx @@ -27,11 +27,25 @@ const SignupWrapper = ({ setIsLoading(true); setLoadingState(true); + // Better Auth treats a relative `callbackURL` as relative to the API + // host that handled the OAuth callback (e.g. api.boundlessfi.xyz), + // not the frontend host. The previous default of '/' caused + // successful sign-ups to land on the API host's root, so users saw + // a blank/404 page and thought sign-up had failed — yet the session + // cookie was already set, so a later cache clear silently logged + // them in. Always send an absolute URL pointing at the frontend. + const callbackURL = + typeof window !== 'undefined' + ? window.location.origin + : ( + process.env.NEXT_PUBLIC_APP_URL || 'https://boundlessfi.xyz' + ).replace(/\/$/, ''); + try { await authClient.signIn.social( { provider: 'google', - callbackURL: process.env.NEXT_PUBLIC_APP_URL || '/', + callbackURL, }, { onRequest: () => {