Open History to see the last commit
1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 buildConnectAuthorizeRequestUrl,
5 connectAuthorizeRequestCode,
6 connectLoopbackCancelUrl,
7 connectLoopbackRedirectUri,
8 readConnectAuthorizeRequest,
9} from "./connectAuth.ts";
10
11describe("connectAuth", () => {
12 it("round-trips state, challenge, and loopback port through the authorize URL fragment", () => {
13 const url = buildConnectAuthorizeRequestUrl({
14 hostedAppUrl: "https://app.t3.codes",
15 state: "q7mK9xV2pL4nR8sT6wYzAQ",
16 challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
17 loopbackPort: 34338,
18 });
19 const parsed = new URL(url);
20
21 expect(parsed.origin).toBe("https://app.t3.codes");
22 expect(parsed.pathname).toBe("/connect");
23 expect(parsed.search).toBe("");
24 expect(readConnectAuthorizeRequest(parsed)).toEqual({
25 state: "q7mK9xV2pL4nR8sT6wYzAQ",
26 challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
27 loopbackPort: 34338,
28 });
29 expect(connectLoopbackRedirectUri(34338)).toBe("http://127.0.0.1:34338/callback");
30 });
31
32 it("carries the CLI device label through the fragment", () => {
33 const parsed = new URL(
34 buildConnectAuthorizeRequestUrl({
35 hostedAppUrl: "https://app.t3.codes",
36 state: "state-1",
37 challenge: "challenge-1",
38 loopbackPort: 34338,
39 device: " maria-mbp \u00b7 zsh ",
40 }),
41 );
42
43 expect(parsed.search).toBe("");
44 expect(readConnectAuthorizeRequest(parsed)?.device).toBe("maria-mbp \u00b7 zsh");
45 });
46
47 it("derives the same short code from the request state on both sides", () => {
48 const code = connectAuthorizeRequestCode("q7mK9xV2pL4nR8sT6wYzAQ");
49
50 expect(code).toMatch(/^[0-9A-HJKMNP-TV-Z]{4}-[0-9A-HJKMNP-TV-Z]{4}$/);
51 expect(connectAuthorizeRequestCode("q7mK9xV2pL4nR8sT6wYzAQ")).toBe(code);
52 expect(connectAuthorizeRequestCode("q7mK9xV2pL4nR8sT6wYzAR")).not.toBe(code);
53 });
54
55 it("cancels through the loopback callback with the OAuth access_denied error", () => {
56 const url = new URL(
57 connectLoopbackCancelUrl({ state: "state-1", challenge: "challenge-1", loopbackPort: 34338 }),
58 );
59
60 expect(`${url.origin}${url.pathname}`).toBe("http://127.0.0.1:34338/callback");
61 expect(url.searchParams.get("error")).toBe("access_denied");
62 expect(url.searchParams.get("state")).toBe("state-1");
63 });
64
65 it("rejects authorize requests missing state, challenge, or port", () => {
66 expect(readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect"))).toBeNull();
67 expect(
68 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&port=34338")),
69 ).toBeNull();
70 expect(
71 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#challenge=abc&port=34338")),
72 ).toBeNull();
73 expect(
74 readConnectAuthorizeRequest(new URL("https://app.t3.codes/connect#state=abc&challenge=abc")),
75 ).toBeNull();
76 });
77
78 it("rejects authorize requests whose loopback port is corrupted", () => {
79 for (const port of ["", "abc", "-1", "0", "65536", "34338x", "34 38"]) {
80 const url = new URL(
81 `https://app.t3.codes/connect#state=state-1&challenge=challenge-1&port=${encodeURIComponent(port)}`,
82 );
83 expect(readConnectAuthorizeRequest(url), port).toBeNull();
84 }
85 });
86});