fix(kiro): align auth flows with CLIProxyAPIPlus

- auto-select Builder ID for the default Kiro AWS auth flow

- support IDC auth flags and callback-based Kiro paste replay

- update regression coverage for Kiro auth routing
This commit is contained in:
Tam Nhu Tran committed 2026-04-05 02:04:11 -04:00
1 parent 14c00dc665
commit 0fbea0f335
11 files changed
+501 -82

No files matched your search

@@ -20,8 +20,18 @@ describe('auth-types paste-callback start path', () => {
expect(getPasteCallbackStartPath('ghcp')).toBe('/v0/management/github-auth-url?is_webui=true');
});
it('keeps Kiro on the legacy start route for paste-callback mode', () => {
expect(getPasteCallbackStartPath('kiro')).toBe('/oauth/kiro/start');
it('maps Kiro management-supported methods to the management auth-url route', () => {
expect(getPasteCallbackStartPath('kiro')).toBe(
'/v0/management/kiro-auth-url?is_webui=true&method=aws'
);
expect(getPasteCallbackStartPath('kiro', { kiroMethod: 'google' })).toBe(
'/v0/management/kiro-auth-url?is_webui=true&method=google'
);
});
it('returns null for Kiro CLI-only paste-callback modes', () => {
expect(getPasteCallbackStartPath('kiro', { kiroMethod: 'aws-authcode' })).toBeNull();
expect(getPasteCallbackStartPath('kiro', { kiroMethod: 'idc' })).toBeNull();
});
it('still exposes the generic management auth-url helper', () => {
@@ -39,11 +39,10 @@ describe('requestPasteCallbackStart', () => {
expect(request.headers['Content-Type']).toBeUndefined();
});
it('keeps kiro on the legacy start route with POST', async () => {
it('uses the Kiro management auth-url route for paste-callback compatible methods', async () => {
mockFetch([
{
url: /\/oauth\/kiro\/start$/,
method: 'POST',
url: /\/v0\/management\/kiro-auth-url\?is_webui=true&method=aws$/,
response: { auth_url: 'https://auth.example.com/kiro' },
},
]);
@@ -51,15 +50,29 @@ describe('requestPasteCallbackStart', () => {
const { requestPasteCallbackStart } = await import(
`../../../src/cliproxy/auth/oauth-handler?request-kiro-start=${Date.now()}`
);
const startData = await requestPasteCallbackStart('kiro', remoteTarget);
const startData = await requestPasteCallbackStart('kiro', remoteTarget, {
kiroMethod: 'aws',
});
expect(startData.auth_url).toBe('https://auth.example.com/kiro');
const [request] = getCapturedFetchRequests();
expect(request.url).toBe('https://proxy.example.com:8317/oauth/kiro/start');
expect(request.method).toBe('POST');
expect(request.url).toBe(
'https://proxy.example.com:8317/v0/management/kiro-auth-url?is_webui=true&method=aws'
);
expect(request.method).toBe('GET');
expect(request.headers['Authorization']).toBe('Bearer test-mgmt-key');
expect(request.headers['Content-Type']).toBe('application/json');
expect(request.headers['Content-Type']).toBeUndefined();
});
it('throws for Kiro methods that require the local callback server flow', async () => {
const { requestPasteCallbackStart } = await import(
`../../../src/cliproxy/auth/oauth-handler?request-kiro-authcode-start=${Date.now()}`
);
await expect(
requestPasteCallbackStart('kiro', remoteTarget, { kiroMethod: 'aws-authcode' })
).rejects.toThrow(/paste-callback start is not available/i);
});
});
@@ -21,7 +21,9 @@ import {
import {
DEFAULT_KIRO_AUTH_METHOD,
getKiroCallbackPort,
getKiroCLIAuthArgs,
getKiroCLIAuthFlag,
normalizeKiroIDCFlow,
normalizeKiroAuthMethod,
OAUTH_CALLBACK_PORTS as AUTH_CALLBACK_PORTS,
toKiroManagementMethod,
@@ -136,20 +138,30 @@ describe('provider-capabilities', () => {
expect(DEFAULT_KIRO_AUTH_METHOD).toBe('aws');
expect(normalizeKiroAuthMethod()).toBe('aws');
expect(normalizeKiroAuthMethod('GOOGLE')).toBe('google');
expect(normalizeKiroAuthMethod('IDC')).toBe('idc');
expect(normalizeKiroAuthMethod('not-valid')).toBe('aws');
expect(normalizeKiroIDCFlow()).toBe('authcode');
expect(normalizeKiroIDCFlow('DEVICE')).toBe('device');
expect(getKiroCLIAuthFlag('aws')).toBe('--kiro-aws-login');
expect(getKiroCLIAuthFlag('aws-authcode')).toBe('--kiro-aws-authcode');
expect(getKiroCLIAuthFlag('google')).toBe('--kiro-google-login');
expect(getKiroCLIAuthFlag('idc')).toBe('--kiro-idc-login');
expect(getKiroCLIAuthArgs('idc', { idcStartUrl: 'https://d-123.awsapps.com/start' })).toEqual(
['--kiro-idc-login', '--kiro-idc-start-url', 'https://d-123.awsapps.com/start', '--kiro-idc-flow', 'authcode']
);
expect(getKiroCallbackPort('aws')).toBeNull();
expect(getKiroCallbackPort('google')).toBe(9876);
expect(getKiroCallbackPort('github')).toBe(9876);
expect(getKiroCallbackPort('aws-authcode')).toBe(9876);
expect(getKiroCallbackPort('idc')).toBe(9876);
expect(getKiroCallbackPort('idc', { idcFlow: 'device' })).toBeNull();
expect(toKiroManagementMethod('aws')).toBe('aws');
expect(toKiroManagementMethod('aws-authcode')).toBe('aws');
expect(toKiroManagementMethod('google')).toBe('google');
expect(toKiroManagementMethod('github')).toBe('github');
expect(toKiroManagementMethod('idc')).toBeNull();
});
});
@@ -25,6 +25,12 @@ describe('cliproxy-auth-routes start-url guard', () => {
);
});
it('rejects Kiro idc method on start-url', () => {
expect(getStartUrlUnsupportedReason('kiro', { kiroMethod: 'idc' })).toContain(
"Kiro method 'idc' uses CLI auth flow"
);
});
it('allows authorization code providers', () => {
expect(getStartUrlUnsupportedReason('gemini')).toBeNull();
expect(getStartUrlUnsupportedReason('codex')).toBeNull();