1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 buildConnectAuthorizeRequestUrl,
5 buildConnectClerkAuthorizeUrl,
6 connectLoopbackRedirectUri,
7 readConnectAuthorizeRequest,
8} from "./connectAuth.ts";
9
10describe("connectAuth", () => {
11 it("round-trips state, challenge, and loopback port through the authorize URL fragment", () => {
12 const url = buildConnectAuthorizeRequestUrl({
13 hostedAppUrl: "https://app.t3.codes",
14 state: "q7mK9xV2pL4nR8sT6wYzAQ",
15 challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
16 loopbackPort: 34338,
17 });
18 const parsed = new URL(url);
19
20 expect(parsed.origin).toBe("https://app.t3.codes");
21 expect(parsed.pathname).toBe("/connect");
22 expect(parsed.search).toBe("");
23 expect(readConnectAuthorizeRequest(parsed)).toEqual({
24 state: "q7mK9xV2pL4nR8sT6wYzAQ",
25 challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
26 loopbackPort: 34338,
27 });
28 expect(connectLoopbackRedirectUri(34338)).toBe("http://127.0.0.1:34338/callback");
29 });
30
31 it("rejects authorize requests missing state, challenge, or port", () => {
32 expect(readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect"))).toBeNull();
33 expect(
34 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&port=34338")),
35 ).toBeNull();
36 expect(
37 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#challenge=abc&port=34338")),
38 ).toBeNull();
39 expect(
40 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&challenge=abc")),
41 ).toBeNull();
42 });
43
44 it("rejects authorize requests whose loopback port is corrupted", () => {
45 for (const port of ["", "abc", "-1", "0", "65536", "34338x", "34 38"]) {
46 const url = new URL(
47 `https://app.t3.codes/connect#state=state-1&challenge=challenge-1&port=${encodeURIComponent(port)}`,
48 );
49 expect(readConnectAuthorizeRequest(url), port).toBeNull();
50 }
51 });
52
53 it("builds a PKCE authorize URL against the Clerk endpoint", () => {
54 const url = new URL(
55 buildConnectClerkAuthorizeUrl({
56 authorizationEndpoint: "https://clerk.t3.codes/oauth/authorize",
57 clientId: "oauthapp_123",
58 redirectUri: connectLoopbackRedirectUri(34338),
59 scopes: ["openid", "profile", "email", "offline_access"],
60 state: "state-1",
61 challenge: "challenge-1",
62 }),
63 );
64
65 expect(url.origin).toBe("https://clerk.t3.codes");
66 expect(url.pathname).toBe("/oauth/authorize");
67 expect(url.searchParams.get("client_id")).toBe("oauthapp_123");
68 expect(url.searchParams.get("redirect_uri")).toBe("http://127.0.0.1:34338/callback");
69 expect(url.searchParams.get("response_type")).toBe("code");
70 expect(url.searchParams.get("scope")).toBe("openid profile email offline_access");
71 expect(url.searchParams.get("state")).toBe("state-1");
72 expect(url.searchParams.get("code_challenge")).toBe("challenge-1");
73 expect(url.searchParams.get("code_challenge_method")).toBe("S256");
74 });
75});