diff --git a/apps/web/src/components/clerk/authRedirect.test.ts b/apps/web/src/components/clerk/authRedirect.test.ts new file mode 100644 index 00000000000..4c4cd72d932 --- /dev/null +++ b/apps/web/src/components/clerk/authRedirect.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { resolveClerkSignInProps } from "./authRedirect"; + +describe("resolveClerkSignInProps", () => { + it("returns to the current browser URL on the web", () => { + const href = "https://app.t3.codes/connect?state=state-1#details"; + expect(resolveClerkSignInProps(href, false)).toEqual({ forceRedirectUrl: href }); + }); + + it("omits the redirect override on packaged desktop", () => { + expect(resolveClerkSignInProps("t3code://app/#/settings/general", true)).toEqual({}); + }); + + it("omits the redirect override on development desktop", () => { + expect(resolveClerkSignInProps("t3code-dev://app/#/settings/general", true)).toEqual({}); + }); +}); diff --git a/apps/web/src/components/clerk/authRedirect.ts b/apps/web/src/components/clerk/authRedirect.ts new file mode 100644 index 00000000000..13331a27798 --- /dev/null +++ b/apps/web/src/components/clerk/authRedirect.ts @@ -0,0 +1,12 @@ +export interface ClerkSignInProps { + forceRedirectUrl?: string; +} + +// Clerk's native-app allowlist only authorizes the bare renderer root +// (t3code://app/), which @clerk/electron's OAuth transport already supplies, +// so any page-derived redirect override gets the whole sign-in request +// rejected. On Electron, omit the override and let Clerk use its defaults. +export function resolveClerkSignInProps(href: string, isElectron: boolean): ClerkSignInProps { + if (isElectron) return {}; + return { forceRedirectUrl: href }; +} diff --git a/apps/web/src/components/clerk/useT3ConnectAuthPrompt.tsx b/apps/web/src/components/clerk/useT3ConnectAuthPrompt.tsx index 3a62a5a8589..859a122ffe4 100644 --- a/apps/web/src/components/clerk/useT3ConnectAuthPrompt.tsx +++ b/apps/web/src/components/clerk/useT3ConnectAuthPrompt.tsx @@ -1,9 +1,12 @@ import { useClerk } from "@clerk/react"; +import { isElectron } from "../../env"; +import { resolveClerkSignInProps } from "./authRedirect"; + export function useT3ConnectAuthPrompt() { const clerk = useClerk(); const openAuthPrompt = () => { - clerk.openSignIn({ forceRedirectUrl: window.location.href }); + clerk.openSignIn(resolveClerkSignInProps(window.location.href, isElectron)); }; return { authPrompt: null, openAuthPrompt }; } diff --git a/apps/web/src/components/cloud/ConnectCliAuthSurface.tsx b/apps/web/src/components/cloud/ConnectCliAuthSurface.tsx index 40ddc4c3dd9..b216f543316 100644 --- a/apps/web/src/components/cloud/ConnectCliAuthSurface.tsx +++ b/apps/web/src/components/cloud/ConnectCliAuthSurface.tsx @@ -8,8 +8,10 @@ import { readConnectCliCallbackResult, rememberConnectCliAuthState, } from "../../cloud/connectCliAuth"; +import { isElectron } from "../../env"; import { useCopyToClipboard } from "../../hooks/useCopyToClipboard"; import { AuthSurfaceShell } from "../auth/AuthSurfaceShell"; +import { resolveClerkSignInProps } from "../clerk/authRedirect"; import { Button } from "../ui/button"; function ConnectCliAuthMessage({ @@ -59,7 +61,7 @@ export function ConnectCliAuthorizeSurface() { if (!isSignedIn) { if (!signInOpened.current) { signInOpened.current = true; - clerk.openSignIn({ forceRedirectUrl: window.location.href }); + clerk.openSignIn(resolveClerkSignInProps(window.location.href, isElectron)); } return; } @@ -95,7 +97,9 @@ export function ConnectCliAuthorizeSurface() {