Add auth retry tests
This commit is contained in:
parent
41c36f2926
commit
f36be7254e
10
src/cli.ts
10
src/cli.ts
@ -791,7 +791,7 @@ export async function handleAuth(runtime: Awaited<ReturnType<typeof createRuntim
|
||||
logInfo(`Authorization complete. ${tools.length} tool${tools.length === 1 ? '' : 's'} available.`);
|
||||
return;
|
||||
} catch (error) {
|
||||
if (attempt === 0 && error instanceof Error && /Unauthorized/i.test(error.message)) {
|
||||
if (attempt === 0 && shouldRetryAuthError(error)) {
|
||||
logWarn('Server signaled OAuth after the initial attempt. Retrying with browser flow...');
|
||||
continue;
|
||||
}
|
||||
@ -801,6 +801,14 @@ export async function handleAuth(runtime: Awaited<ReturnType<typeof createRuntim
|
||||
}
|
||||
}
|
||||
|
||||
function shouldRetryAuthError(error: unknown): boolean {
|
||||
const message = error instanceof Error ? error.message : typeof error === 'string' ? error : '';
|
||||
if (!message) {
|
||||
return false;
|
||||
}
|
||||
return /unauthorized|invalid[_-]?token|\b(401|403)\b/i.test(message);
|
||||
}
|
||||
|
||||
function looksLikeHttpUrl(value: string): boolean {
|
||||
return /^https?:\/\//i.test(value);
|
||||
}
|
||||
|
||||
39
tests/cli-auth-retry.test.ts
Normal file
39
tests/cli-auth-retry.test.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
process.env.MCPORTER_DISABLE_AUTORUN = '1';
|
||||
const cliModulePromise = import('../src/cli.js');
|
||||
|
||||
const baseDefinition = {
|
||||
name: 'adhoc-server',
|
||||
command: { kind: 'http' as const, url: new URL('https://example.com/mcp') },
|
||||
source: { kind: 'local' as const, path: '<adhoc>' },
|
||||
};
|
||||
|
||||
describe('handleAuth retry logic', () => {
|
||||
it('retries once when the first attempt is unauthorized', async () => {
|
||||
const { handleAuth } = await cliModulePromise;
|
||||
const runtime = {
|
||||
registerDefinition: vi.fn(),
|
||||
getDefinition: vi.fn().mockReturnValue(baseDefinition),
|
||||
listTools: vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce(new Error('SSE error: Non-200 status code (401)'))
|
||||
.mockResolvedValueOnce([{ name: 'ok' }]),
|
||||
} as unknown as Awaited<ReturnType<typeof import('../src/runtime.js')['createRuntime']>>;
|
||||
|
||||
await expect(handleAuth(runtime, ['adhoc-server'])).resolves.toBeUndefined();
|
||||
expect(runtime.listTools).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('throws after the second unauthorized attempt', async () => {
|
||||
const { handleAuth } = await cliModulePromise;
|
||||
const runtime = {
|
||||
registerDefinition: vi.fn(),
|
||||
getDefinition: vi.fn().mockReturnValue(baseDefinition),
|
||||
listTools: vi.fn().mockRejectedValue(new Error('SSE error: Non-200 status code (401)')),
|
||||
} as unknown as Awaited<ReturnType<typeof import('../src/runtime.js')['createRuntime']>>;
|
||||
|
||||
await expect(handleAuth(runtime, ['adhoc-server'])).rejects.toThrow(/Failed to authorize/);
|
||||
expect(runtime.listTools).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user