mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 18:16:08 +00:00
- keep headless paste routing aligned with the selected Kiro auth method - validate local callback replay targets and add prompt cancellation safeguards - wire IDC params through the dashboard start route and support equals-form CLI flags
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import { describe, expect, it } from 'bun:test';
|
|
import {
|
|
extractLikelyAuthFailureFromStderr,
|
|
getExpectedLocalCallback,
|
|
validateManualCallbackUrl,
|
|
} from '../../../src/cliproxy/auth/oauth-process';
|
|
|
|
describe('oauth-process stderr parsing', () => {
|
|
it('ignores non-ghcp providers', () => {
|
|
const stderr =
|
|
'time="2026-03-03T10:00:00Z" level=error msg="GitHub Copilot authentication failed: example"';
|
|
|
|
expect(extractLikelyAuthFailureFromStderr('qwen', stderr)).toBeNull();
|
|
});
|
|
|
|
it('extracts copilot verification failures from logrus lines', () => {
|
|
const stderr =
|
|
'time="2026-03-03T10:00:00Z" level=error msg="GitHub Copilot authentication failed: github-copilot: failed to verify Copilot access - you may not have an active Copilot subscription: 403 Forbidden"';
|
|
|
|
expect(extractLikelyAuthFailureFromStderr('ghcp', stderr)).toBe(
|
|
'github-copilot: failed to verify Copilot access - you may not have an active Copilot subscription: 403 Forbidden'
|
|
);
|
|
});
|
|
|
|
it('extracts generic authentication failure lines', () => {
|
|
const stderr = 'level=error msg="Authentication failed: state mismatch"';
|
|
|
|
expect(extractLikelyAuthFailureFromStderr('ghcp', stderr)).toBe('state mismatch');
|
|
});
|
|
|
|
it('caps extracted message length to prevent noisy broadcasts', () => {
|
|
const longSuffix = 'x'.repeat(400);
|
|
const stderr = `level=error msg="Authentication failed: ${longSuffix}"`;
|
|
|
|
const parsed = extractLikelyAuthFailureFromStderr('ghcp', stderr);
|
|
expect(parsed).not.toBeNull();
|
|
expect((parsed as string).length).toBe(240);
|
|
});
|
|
});
|
|
|
|
describe('oauth-process manual callback validation', () => {
|
|
const authUrl =
|
|
'https://oidc.example.com/authorize?redirect_uri=http%3A%2F%2F127.0.0.1%3A9876%2Foauth%2Fcallback&state=test-state';
|
|
|
|
it('extracts the expected local callback target from the auth URL', () => {
|
|
expect(getExpectedLocalCallback(authUrl)).toEqual({
|
|
origin: 'http://127.0.0.1:9876',
|
|
pathname: '/oauth/callback',
|
|
state: 'test-state',
|
|
});
|
|
});
|
|
|
|
it('accepts matching loopback callback URLs', () => {
|
|
expect(
|
|
validateManualCallbackUrl(
|
|
'http://127.0.0.1:9876/oauth/callback?code=abc123&state=test-state',
|
|
authUrl
|
|
)
|
|
).toBeNull();
|
|
});
|
|
|
|
it('rejects non-loopback callback URLs', () => {
|
|
expect(
|
|
validateManualCallbackUrl(
|
|
'https://evil.example.com/oauth/callback?code=abc123&state=test-state',
|
|
authUrl
|
|
)
|
|
).toContain('local OAuth callback server');
|
|
});
|
|
|
|
it('rejects callback URLs with the wrong path or state', () => {
|
|
expect(
|
|
validateManualCallbackUrl(
|
|
'http://127.0.0.1:9876/not-the-callback?code=abc123&state=test-state',
|
|
authUrl
|
|
)
|
|
).toContain('expected local OAuth callback target');
|
|
|
|
expect(
|
|
validateManualCallbackUrl(
|
|
'http://127.0.0.1:9876/oauth/callback?code=abc123&state=wrong-state',
|
|
authUrl
|
|
)
|
|
).toContain('state does not match');
|
|
});
|
|
});
|