From eff084a1f9161b54066d773a615cd8ed54f398fd Mon Sep 17 00:00:00 2001 From: Sreeram Sreedhar Date: Tue, 23 Jun 2026 12:37:04 -0700 Subject: [PATCH] Use Better Auth desktop handoff --- apps/desktop/src-tauri/src/auth.rs | 19 +-- apps/web/app/auth/desktop/page.tsx | 196 +++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 apps/web/app/auth/desktop/page.tsx diff --git a/apps/desktop/src-tauri/src/auth.rs b/apps/desktop/src-tauri/src/auth.rs index 1b749b6c..725220af 100644 --- a/apps/desktop/src-tauri/src/auth.rs +++ b/apps/desktop/src-tauri/src/auth.rs @@ -13,7 +13,7 @@ use std::{ const KEYCHAIN_SERVICE: &str = "ai.supermemory.desktop"; const KEYCHAIN_USER: &str = "supermemory-api-token"; const KEYCHAIN_API_URL_USER: &str = "supermemory-api-url"; -const DEFAULT_WEB_URL: &str = "https://console.supermemory.ai"; +const DEFAULT_WEB_URL: &str = "https://app.supermemory.ai"; const DEFAULT_BROWSER_API_URL: &str = "https://api.supermemory.ai"; const BROWSER_AUTH_TIMEOUT: Duration = Duration::from_secs(120); #[cfg(debug_assertions)] @@ -320,7 +320,7 @@ fn build_browser_login_url(state: &str, callback_port: u16) -> Result Result("loading") + const [error, setError] = useState(null) + const hasStarted = useRef(false) + + const callback = params.get("callback") + const desktopHostname = params.get("hostname") || "Supermemory Desktop" + const desktopOs = params.get("os") || "desktop" + const desktopCwd = params.get("cwd") || "" + const desktopVersion = params.get("version") || "desktop" + const callbackIsValid = useMemo( + () => (callback ? isValidDesktopCallback(callback) : false), + [callback], + ) + + const shouldRedirectToOnboarding = + !isPending && + !isRestoring && + !!session && + Array.isArray(organizations) && + organizations.length === 0 + + useEffect(() => { + if (isPending || isRestoring) return + if (!session) return + if (organizations === null) return + if (organizations.length > 0) return + + try { + sessionStorage.setItem(PENDING_CONNECT_URL_KEY, window.location.href) + } catch (err) { + console.warn("Failed to store pending desktop auth URL", err) + } + router.replace("/onboarding") + }, [isPending, isRestoring, session, organizations, router]) + + useEffect(() => { + if (isPending || isRestoring || shouldRedirectToOnboarding) return + if (hasStarted.current) return + + if (!callback) { + setStatus("error") + setError("Missing desktop callback URL.") + return + } + if (!callbackIsValid) { + setStatus("error") + setError("Invalid desktop callback URL.") + return + } + if (!session || !org) { + setStatus("error") + setError("Your account is not fully set up yet.") + return + } + + hasStarted.current = true + const callbackUrl = callback + + async function finishDesktopAuth() { + try { + setStatus("creating") + const res = await fetch(`${API_URL}/v3/auth/agent-key`, { + method: "POST", + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + name: "Supermemory Desktop", + permission: "write", + deviceInfo: { + hostname: desktopHostname, + os: desktopOs, + cwd: desktopCwd, + cliVersion: desktopVersion, + }, + }), + }) + + if (!res.ok) { + const data = (await res.json().catch(() => ({}))) as { + message?: string + } + throw new Error(data.message ?? "Failed to create desktop key") + } + + const data = (await res.json()) as { key: string } + setStatus("success") + + const redirectUrl = new URL(callbackUrl) + redirectUrl.searchParams.set("apikey", data.key) + redirectUrl.searchParams.set("api_url", API_URL) + window.location.href = redirectUrl.toString() + } catch (err) { + setStatus("error") + setError( + err instanceof Error ? err.message : "Failed to finish desktop login", + ) + } + } + + void finishDesktopAuth() + }, [ + callback, + callbackIsValid, + desktopCwd, + desktopHostname, + desktopOs, + desktopVersion, + isPending, + isRestoring, + org, + session, + shouldRedirectToOnboarding, + ]) + + if (status === "error") { + return ( +
+
+ +
+

+ Desktop login failed +

+

{error}

+
+
+
+ ) + } + + return ( +
+
+ +

+ {status === "success" + ? "Returning to Supermemory Desktop..." + : "Finishing desktop login..."} +

+
+
+ ) +} + +export default function DesktopAuthPage() { + return ( + + + + } + > + + + ) +}