fix(auth): complete Google OAuth after SDK boot (was stuck on ?code=…#identify)
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.
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
|||||||
PasswordStrength,
|
PasswordStrength,
|
||||||
} from "./bits";
|
} from "./bits";
|
||||||
import { lookupAccount, maskEmail, type Account } from "./data";
|
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";
|
import { isShellConfigured } from "@/lib/appshell";
|
||||||
|
|
||||||
// Map the portal's social button ids to Supabase OAuth provider ids.
|
// 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() {
|
export function LoginFlow() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { login, loginWithOAuth, completeOAuthLogin } = useAuth();
|
const { login, loginWithOAuth, completeOAuthLogin } = useAuth();
|
||||||
|
const { ready } = useAppShell();
|
||||||
const [step, setStep] = useState<Step>("identify");
|
const [step, setStep] = useState<Step>("identify");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [account, setAccount] = useState<Account | null>(null);
|
const [account, setAccount] = useState<Account | null>(null);
|
||||||
@@ -70,11 +71,22 @@ export function LoginFlow() {
|
|||||||
if (!isShellConfigured()) return;
|
if (!isShellConfigured()) return;
|
||||||
const code = new URLSearchParams(window.location.search).get("code");
|
const code = new URLSearchParams(window.location.search).get("code");
|
||||||
if (!code) return;
|
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");
|
setStep("connecting");
|
||||||
completeOAuthLogin(code)
|
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"); });
|
.catch(() => { setFlash("Sign-in with that provider didn't complete. Try again."); replace("identify"); });
|
||||||
}, [completeOAuthLogin, router]);
|
}, [ready, completeOAuthLogin, router]);
|
||||||
|
|
||||||
/* ---- auth resolution ---- */
|
/* ---- auth resolution ---- */
|
||||||
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
|
function afterAuth(factor: "password" | "passkey" | "otp" | "totp" | "push" | "social") {
|
||||||
|
|||||||
Reference in New Issue
Block a user