Files
CodexDash/apps/api/src/codex/codex-oauth.spec.ts

84 lines
2.8 KiB
TypeScript

import {
buildCodexAuthorizeUrl,
createPkcePair,
extractCodexIdentity,
renderCodexOauthCallbackHtml,
} from './codex-oauth';
describe('codex-oauth helpers', () => {
it('builds the OpenAI authorize URL with Codex-specific PKCE parameters', () => {
const url = new URL(
buildCodexAuthorizeUrl({
state: 'state-123',
codeChallenge: 'challenge-abc',
redirectUri: 'http://localhost:1455/auth/callback',
}),
);
expect(url.origin + url.pathname).toBe(
'https://auth.openai.com/oauth/authorize',
);
expect(url.searchParams.get('response_type')).toBe('code');
expect(url.searchParams.get('client_id')).toBe(
'app_EMoamEEZ73f0CkXaXp7hrann',
);
expect(url.searchParams.get('redirect_uri')).toBe(
'http://localhost:1455/auth/callback',
);
expect(url.searchParams.get('scope')).toBe(
'openid profile email offline_access',
);
expect(url.searchParams.get('code_challenge')).toBe('challenge-abc');
expect(url.searchParams.get('code_challenge_method')).toBe('S256');
expect(url.searchParams.get('state')).toBe('state-123');
expect(url.searchParams.get('originator')).toBe('codex_cli_rs');
expect(url.searchParams.get('codex_cli_simplified_flow')).toBe('true');
expect(url.searchParams.get('id_token_add_organizations')).toBe('true');
});
it('creates a valid PKCE verifier/challenge pair', () => {
const pair = createPkcePair(Buffer.alloc(32, 7));
expect(pair.verifier).toBe('BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc');
expect(pair.challenge).toBe('3Ev4DHdHPRMPoN6GukAY_pi7IUAF5qWJHRK6kURvnoE');
});
it('extracts account identity fields from the id token payload', () => {
const header = Buffer.from(JSON.stringify({ alg: 'none' })).toString(
'base64url',
);
const payload = Buffer.from(
JSON.stringify({
email: 'operator@example.com',
exp: 1_800_000_000,
'https://api.openai.com/auth': {
chatgpt_account_id: 'acct_123',
chatgpt_plan_type: 'pro',
},
}),
).toString('base64url');
const token = `${header}.${payload}.signature`;
expect(extractCodexIdentity(token)).toEqual({
email: 'operator@example.com',
accountId: 'acct_123',
planType: 'pro',
expiresAt: new Date(1_800_000_000 * 1000),
});
});
it('renders callback html that reports completion back to the frontend window', () => {
const html = renderCodexOauthCallbackHtml({
attemptId: 'attempt_123',
status: 'success',
frontendOrigin: 'http://localhost:5173',
message: 'Connected successfully',
});
expect(html).toContain('codexdash:oauth-complete');
expect(html).toContain('attempt_123');
expect(html).toContain('Connected successfully');
expect(html).toContain('http://localhost:5173');
});
});