| 1 | // @effect-diagnostics nodeBuiltinImport:off globalFetch:off - Tests exercise the real native loopback listener without an OpenAI account. |
| 2 | import * as NodeHttp from "node:http"; |
| 3 | import { describe, expect, it } from "vite-plus/test"; |
| 4 | import { codexAuthDeliveryUrl, readCodexAuthDelivery } from "@t3tools/shared/codexAuthHandoff"; |
| 5 | import { EnvironmentId, ProviderInstanceId } from "@t3tools/contracts"; |
| 6 | import { receiveCodexAuthCallback, cancelCodexAuthCallback } from "./CodexAuthCallback.ts"; |
| 7 | |
| 8 | async function freePort() { |
| 9 | const server = NodeHttp.createServer(); |
| 10 | await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve)); |
| 11 | const address = server.address(); |
| 12 | if (!address || typeof address === "string") throw new Error("address"); |
| 13 | await new Promise<void>((resolve) => server.close(() => resolve())); |
| 14 | return address.port; |
| 15 | } |
| 16 | function request(port: number, state = "a".repeat(43)) { |
| 17 | const url = new URL("https://auth.openai.com/api/accounts/authorize"); |
| 18 | url.search = new URLSearchParams({ |
| 19 | client_id: "dynamic_agent_client", |
| 20 | response_type: "code", |
| 21 | redirect_uri: `http://127.0.0.1:${port}/auth/callback`, |
| 22 | state, |
| 23 | code_challenge_method: "S256", |
| 24 | code_challenge: "b".repeat(43), |
| 25 | }).toString(); |
| 26 | return url.toString(); |
| 27 | } |
| 28 | function callback(authorizationUrl: string) { |
| 29 | const request = new URL(authorizationUrl); |
| 30 | const url = new URL(request.searchParams.get("redirect_uri")!); |
| 31 | url.search = new URLSearchParams({ |
| 32 | state: request.searchParams.get("state")!, |
| 33 | code: "test-code", |
| 34 | client_id: "oaiapp_test", |
| 35 | }).toString(); |
| 36 | return url.toString(); |
| 37 | } |
| 38 | |
| 39 | describe("desktop Codex callback helper", () => { |
| 40 | it("binds before opening sign-in, ignores a foreign response, and returns only the code callback", async () => { |
| 41 | const authorizationUrl = request(await freePort()); |
| 42 | const expected = callback(authorizationUrl); |
| 43 | const received = await receiveCodexAuthCallback(authorizationUrl, async () => { |
| 44 | const invalid = new URL(expected); |
| 45 | invalid.searchParams.set("state", "foreign"); |
| 46 | expect((await fetch(invalid)).status).toBe(400); |
| 47 | const response = await fetch(expected); |
| 48 | expect(response.headers.get("cache-control")).toBe("no-store"); |
| 49 | expect(await response.text()).not.toContain("test-code"); |
| 50 | return true; |
| 51 | }); |
| 52 | expect(received).toBe(expected); |
| 53 | }); |
| 54 | it("returns hosted web to the exact instance and environment without putting the code in its query", async () => { |
| 55 | const authorizationUrl = request(await freePort()); |
| 56 | const expected = callback(authorizationUrl); |
| 57 | const input = { |
| 58 | authorizationUrl, |
| 59 | returnUrl: "https://app.t3.codes/settings/providers?environmentId=remote-one&instanceId=work", |
| 60 | environmentId: EnvironmentId.make("remote-one"), |
| 61 | instanceId: ProviderInstanceId.make("work"), |
| 62 | flowId: "flow-one", |
| 63 | }; |
| 64 | await receiveCodexAuthCallback( |
| 65 | authorizationUrl, |
| 66 | async () => { |
| 67 | const response = await fetch(expected, { redirect: "manual" }); |
| 68 | expect(response.status).toBe(303); |
| 69 | const delivery = response.headers.get("location")!; |
| 70 | expect(new URL(delivery).searchParams.has("code")).toBe(false); |
| 71 | expect(readCodexAuthDelivery(delivery)?.callbackUrl).toBe(expected); |
| 72 | expect(readCodexAuthDelivery(delivery)?.returnUrl).toBe(input.returnUrl); |
| 73 | return true; |
| 74 | }, |
| 75 | (url) => codexAuthDeliveryUrl(input, url), |
| 76 | ); |
| 77 | }); |
| 78 | it("cancels and releases its listener so exact-port reauthorization can run again", async () => { |
| 79 | const authorizationUrl = request(await freePort()); |
| 80 | await expect( |
| 81 | receiveCodexAuthCallback(authorizationUrl, async () => { |
| 82 | cancelCodexAuthCallback(authorizationUrl); |
| 83 | return true; |
| 84 | }), |
| 85 | ).rejects.toThrow("cancelled"); |
| 86 | expect( |
| 87 | await receiveCodexAuthCallback(authorizationUrl, async () => { |
| 88 | await fetch(callback(authorizationUrl)); |
| 89 | return true; |
| 90 | }), |
| 91 | ).toBe(callback(authorizationUrl)); |
| 92 | }); |
| 93 | it("allows two accounts to complete independently", async () => { |
| 94 | const a = request(await freePort(), "a".repeat(43)); |
| 95 | const b = request(await freePort(), "c".repeat(43)); |
| 96 | const openedA = Promise.withResolvers<void>(); |
| 97 | const openedB = Promise.withResolvers<void>(); |
| 98 | const receiveA = receiveCodexAuthCallback(a, async () => { |
| 99 | openedA.resolve(); |
| 100 | await openedB.promise; |
| 101 | await fetch(callback(a)); |
| 102 | return true; |
| 103 | }); |
| 104 | const receiveB = receiveCodexAuthCallback(b, async () => { |
| 105 | openedB.resolve(); |
| 106 | await openedA.promise; |
| 107 | await fetch(callback(b)); |
| 108 | return true; |
| 109 | }); |
| 110 | expect(await Promise.all([receiveA, receiveB])).toEqual([callback(a), callback(b)]); |
| 111 | }); |
| 112 | }); |