t3-code-android-nightly/packages/shared/src/connectAuth.test.ts
Julius Marminge dc0869b605
feat(server): use Clerk's device authorization grant for headless connect login (#11794)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-14 15:09:28 -07:00

75 lines
3 KiB
TypeScript

import { describe, expect, it } from "vite-plus/test";
import {
buildConnectAuthorizeRequestUrl,
buildConnectClerkAuthorizeUrl,
connectLoopbackRedirectUri,
readConnectAuthorizeRequest,
} from "./connectAuth.ts";
describe("connectAuth", () => {
it("round-trips state, challenge, and loopback port through the authorize URL fragment", () => {
const url = buildConnectAuthorizeRequestUrl({
hostedAppUrl: "https://app.t3.codes",
state: "q7mK9xV2pL4nR8sT6wYzAQ",
challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
loopbackPort: 34338,
});
const parsed = new URL(url);
expect(parsed.origin).toBe("https://app.t3.codes");
expect(parsed.pathname).toBe("/connect");
expect(parsed.search).toBe("");
expect(readConnectAuthorizeRequest(parsed)).toEqual({
state: "q7mK9xV2pL4nR8sT6wYzAQ",
challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
loopbackPort: 34338,
});
expect(connectLoopbackRedirectUri(34338)).toBe("http://127.0.0.1:34338/callback");
});
it("rejects authorize requests missing state, challenge, or port", () => {
expect(readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect"))).toBeNull();
expect(
readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&port=34338")),
).toBeNull();
expect(
readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#challenge=abc&port=34338")),
).toBeNull();
expect(
readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&challenge=abc")),
).toBeNull();
});
it("rejects authorize requests whose loopback port is corrupted", () => {
for (const port of ["", "abc", "-1", "0", "65536", "34338x", "34 38"]) {
const url = new URL(
`https://app.t3.codes/connect#state=state-1&challenge=challenge-1&port=${encodeURIComponent(port)}`,
);
expect(readConnectAuthorizeRequest(url), port).toBeNull();
}
});
it("builds a PKCE authorize URL against the Clerk endpoint", () => {
const url = new URL(
buildConnectClerkAuthorizeUrl({
authorizationEndpoint: "https://clerk.t3.codes/oauth/authorize",
clientId: "oauthapp_123",
redirectUri: connectLoopbackRedirectUri(34338),
scopes: ["openid", "profile", "email", "offline_access"],
state: "state-1",
challenge: "challenge-1",
}),
);
expect(url.origin).toBe("https://clerk.t3.codes");
expect(url.pathname).toBe("/oauth/authorize");
expect(url.searchParams.get("client_id")).toBe("oauthapp_123");
expect(url.searchParams.get("redirect_uri")).toBe("http://127.0.0.1:34338/callback");
expect(url.searchParams.get("response_type")).toBe("code");
expect(url.searchParams.get("scope")).toBe("openid profile email offline_access");
expect(url.searchParams.get("state")).toBe("state-1");
expect(url.searchParams.get("code_challenge")).toBe("challenge-1");
expect(url.searchParams.get("code_challenge_method")).toBe("S256");
});
});