Files
bot-agents/auth_test.ts
T
Danny Kim 7bae0d7237
Check / deno (pull_request) Successful in 36s
Centralize encrypted bot profiles
2026-09-24 05:00:02 +09:00

126 lines
3.4 KiB
TypeScript

import { assertEquals, assertRejects } from "jsr:@std/assert@1";
import {
codexAuthentication,
persistCodexAuth,
retryInvalidToken,
stageCodexAuth,
} from "./auth.ts";
Deno.test("retries once after an invalid refresh token", async () => {
let attempts = 0;
let relogins = 0;
const result = await retryInvalidToken(
() =>
Promise.resolve({
status: { success: false },
error: attempts++ === 0 ? "invalid_refresh_token" : "still failed",
}),
() => {
relogins++;
return Promise.resolve();
},
);
assertEquals({ attempts, relogins, error: result.error }, {
attempts: 2,
relogins: 1,
error: "still failed",
});
});
Deno.test("does not retry an unrelated failure", async () => {
let attempts = 0;
let relogins = 0;
await retryInvalidToken(
() => {
attempts++;
return Promise.resolve({
status: { success: false },
error: "rate limited",
});
},
() => {
relogins++;
return Promise.resolve();
},
);
assertEquals({ attempts, relogins }, { attempts: 1, relogins: 0 });
});
Deno.test("selects API-key login only for a configured Codex token", () => {
assertEquals(codexAuthentication("selected-key"), {
kind: "api-key",
token: "selected-key",
});
assertEquals(codexAuthentication(undefined), { kind: "persistent" });
});
const AUTH = JSON.stringify({
auth_mode: "chatgpt",
tokens: {
access_token: "access",
refresh_token: "refresh",
id_token: "id",
account_id: "account",
},
});
Deno.test("stages and persists only a regular private Codex login", async () => {
if (Deno.build.os === "windows") return;
const root = await Deno.makeTempDir();
try {
const canonical = `${root}/persistent/auth.json`;
await Deno.mkdir(`${root}/persistent`);
await Deno.writeTextFile(canonical, AUTH, { mode: 0o600 });
const home = `${root}/profile`;
await Deno.mkdir(home);
const staged = await stageCodexAuth(
canonical,
home,
Deno.uid()!,
Deno.gid()!,
);
assertEquals(await Deno.readTextFile(staged), AUTH);
assertEquals((await Deno.stat(staged)).mode! & 0o777, 0o600);
const refreshed = JSON.stringify({
...JSON.parse(AUTH),
tokens: { ...JSON.parse(AUTH).tokens, access_token: "refreshed" },
});
await Deno.writeTextFile(staged, refreshed);
await persistCodexAuth(staged, canonical);
assertEquals(await Deno.readTextFile(canonical), refreshed);
assertEquals((await Deno.stat(canonical)).mode! & 0o777, 0o600);
} finally {
await Deno.remove(root, { recursive: true });
}
});
Deno.test("rejects a symlink or malformed Codex login", async () => {
if (Deno.build.os === "windows") return;
const root = await Deno.makeTempDir();
try {
const canonical = `${root}/auth.json`;
const malformed = `${root}/malformed.json`;
const linked = `${root}/linked.json`;
await Deno.writeTextFile(canonical, AUTH, { mode: 0o600 });
await Deno.writeTextFile(malformed, '{"tokens":{}}', { mode: 0o600 });
await Deno.symlink(canonical, linked);
await assertRejects(
() => persistCodexAuth(linked, canonical),
Error,
"regular file",
);
await assertRejects(
() => persistCodexAuth(malformed, canonical),
Error,
"invalid Codex login",
);
} finally {
await Deno.remove(root, { recursive: true });
}
});