Files
aryx/tests/main/mcpOAuthService.test.ts
T
David KayaandCopilot 73595039fc fix: support provider-specific MCP OAuth settings
Use provider-aware OAuth handling instead of a single hardcoded client ID.
GitHub now follows VS Code's GitHub auth setup with the GitHub client ID,
GitHub authorize/token endpoints, prompt=select_account, vscode.dev/redirect,
and JSON-compatible token exchange. Entra keeps the Copilot client ID via a
known provider match, while unknown providers still fall back to metadata
and dynamic registration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 20:23:26 +01:00

79 lines
2.9 KiB
TypeScript

import { describe, expect, mock, test } from 'bun:test';
mock.module('electron', () => {
const electronMock = {
shell: {
openExternal: async () => undefined,
},
};
return {
...electronMock,
default: electronMock,
};
});
const {
buildScopes,
parseTokenResponseBody,
resolveKnownProvider,
} = await import('@main/services/mcpOAuthService');
describe('resolveKnownProvider', () => {
test('matches GitHub OAuth provider', () => {
const provider = resolveKnownProvider('https://github.com/login/oauth');
expect(provider?.id).toBe('github');
expect(provider?.clientId).toBe('01ab8ac9400c4e429b23');
expect(provider?.authorizationEndpoint).toBe('https://github.com/login/oauth/authorize');
expect(provider?.tokenEndpoint).toBe('https://github.com/login/oauth/access_token');
expect(provider?.authorizationParams).toEqual({ prompt: 'select_account' });
});
test('matches Entra OAuth provider', () => {
const provider = resolveKnownProvider('https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0');
expect(provider?.id).toBe('entra');
expect(provider?.clientId).toBe('aebc6443-996d-45c2-90f0-388ff96faa56');
expect(provider?.authorizationEndpoint).toBeUndefined();
expect(provider?.tokenEndpoint).toBeUndefined();
});
test('returns undefined for unknown provider', () => {
expect(resolveKnownProvider('https://auth.example.com')).toBeUndefined();
});
});
describe('buildScopes', () => {
test('uses provider-specific GitHub scopes without offline access', () => {
const provider = resolveKnownProvider('https://github.com/login/oauth');
expect(buildScopes(provider, ['ignored'], ['also-ignored']))
.toBe('codespace gist notifications project read:org read:packages read:project read:user repo user:email workflow write:packages');
});
test('uses protected resource scopes for Entra and appends offline access', () => {
const provider = resolveKnownProvider('https://login.microsoftonline.com/common/v2.0');
expect(buildScopes(provider, ['api://icmmcpapi-prod/mcp.tools'], ['openid']))
.toBe('api://icmmcpapi-prod/mcp.tools offline_access');
});
test('falls back to auth server scopes for unknown providers', () => {
expect(buildScopes(undefined, undefined, ['openid', 'profile']))
.toBe('openid profile offline_access');
});
});
describe('parseTokenResponseBody', () => {
test('parses JSON token responses', () => {
expect(parseTokenResponseBody('{"access_token":"abc","token_type":"Bearer"}', 'application/json'))
.toEqual({ access_token: 'abc', token_type: 'Bearer' });
});
test('parses form-encoded token responses', () => {
expect(parseTokenResponseBody('access_token=abc&scope=repo%20user%3Aemail&token_type=bearer', 'application/x-www-form-urlencoded'))
.toEqual({ access_token: 'abc', scope: 'repo user:email', token_type: 'bearer' });
});
});