From 6e1a895e7e7a2e5cc2810c060f55d70eb7f18752 Mon Sep 17 00:00:00 2001 From: tanweer919 Date: Mon, 13 Jul 2026 01:31:37 +0530 Subject: [PATCH] =?UTF-8?q?fix(auth):=20complete=20Google=20OAuth=20after?= =?UTF-8?q?=20SDK=20boot=20(was=20stuck=20on=20=3Fcode=3D=E2=80=A6#identif?= =?UTF-8?q?y)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OAuth-return effect ran on mount before AppShell finished booting, so completeOAuthLogin no-oped (sdk.auth undefined → null) and fell back to identify, never retrying. Gate it on useAppShell().ready so it runs once auth is up, and strip ?code= from the URL on success. --- src/components/portal/login-flow.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/portal/login-flow.tsx b/src/components/portal/login-flow.tsx index 6186507..16094f0 100644 --- a/src/components/portal/login-flow.tsx +++ b/src/components/portal/login-flow.tsx @@ -9,7 +9,7 @@ import { PasswordStrength, } from "./bits"; import { lookupAccount, maskEmail, type Account } from "./data"; -import { useAuth } from "@abe-kap/appshell-sdk/react"; +import { useAuth, useAppShell } from "@abe-kap/appshell-sdk/react"; import { isShellConfigured } from "@/lib/appshell"; // Map the portal's social button ids to Supabase OAuth provider ids. @@ -25,6 +25,7 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; export function LoginFlow() { const router = useRouter(); const { login, loginWithOAuth, completeOAuthLogin } = useAuth(); + const { ready } = useAppShell(); const [step, setStep] = useState("identify"); const [email, setEmail] = useState(""); const [account, setAccount] = useState(null); @@ -70,11 +71,22 @@ export function LoginFlow() { if (!isShellConfigured()) return; const code = new URLSearchParams(window.location.search).get("code"); if (!code) return; + // Wait until the SDK has booted — completeOAuthLogin no-ops (returns null) if + // sdk.auth isn't ready yet, and this effect only re-runs when `ready` flips. + if (!ready) { setStep("connecting"); return; } setStep("connecting"); completeOAuthLogin(code) - .then((ace) => { if (ace) router.replace("/dashboard"); else replace("identify"); }) + .then((ace) => { + if (ace) { + // Clear the ?code=… from the URL, then enter the app. + window.history.replaceState({}, "", "/portal/login"); + router.replace("/dashboard"); + } else { + replace("identify"); + } + }) .catch(() => { setFlash("Sign-in with that provider didn't complete. Try again."); replace("identify"); }); - }, [completeOAuthLogin, router]); + }, [ready, completeOAuthLogin, router]); /* ---- auth resolution ---- */ function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") { -- 2.52.0