From c67266ccbf571f402812aa5cbbe26c952dcef11e Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Wed, 15 Apr 2026 00:49:51 +0800 Subject: [PATCH] fix(auth): honor ?next= redirect through Google OAuth flow The login page now encodes the ?next= param into the Google OAuth state so the auth callback can redirect to the right destination (e.g. /invite/{id}) after login, instead of always going to /issues. --- apps/web/app/(auth)/login/page.tsx | 11 ++++++++++- apps/web/app/auth/callback/page.tsx | 11 ++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/web/app/(auth)/login/page.tsx b/apps/web/app/(auth)/login/page.tsx index ea0c54c35..78de1dd63 100644 --- a/apps/web/app/(auth)/login/page.tsx +++ b/apps/web/app/(auth)/login/page.tsx @@ -37,6 +37,15 @@ function LoginPageContent() { router.push(ws ? nextUrl : "/onboarding"); }; + // Build Google OAuth state: encode platform + next URL so the callback + // can redirect to the right place after login. + const googleState = [ + platform === "desktop" ? "platform:desktop" : "", + nextUrl !== "/issues" ? `next:${nextUrl}` : "", + ] + .filter(Boolean) + .join(",") || undefined; + return ( p.startsWith("next:")); + const nextUrl = nextPart ? nextPart.slice(5) : null; // strip "next:" prefix const redirectUri = `${window.location.origin}/auth/callback`; @@ -63,7 +66,9 @@ function CallbackContent() { qc.setQueryData(workspaceKeys.list(), wsList); const lastWsId = localStorage.getItem("multica_workspace_id"); const ws = await hydrateWorkspace(wsList, lastWsId); - router.push(ws ? "/issues" : "/onboarding"); + // Honor the ?next= redirect if present (e.g. /invite/{id}) + const defaultDest = ws ? "/issues" : "/onboarding"; + router.push(nextUrl || defaultDest); }) .catch((err) => { setError(err instanceof Error ? err.message : "Login failed");