mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-07 12:18:44 +02:00
feat: implement MCP OAuth 2.1 flow, token storage, and injection
- Create mcpTokenStore: in-memory token storage keyed by normalized server URL with automatic expiry checking - Create mcpOAuthService: full OAuth 2.1 + PKCE flow implementation - Protected Resource Metadata discovery (RFC 9728) - Authorization Server Metadata fetch (RFC 8414) - Dynamic Client Registration (RFC 7591) when no static client ID - PKCE S256 code challenge generation - Local HTTP callback server for auth code receipt - Browser-based consent via Electron shell.openExternal - Authorization code to token exchange - Add startSessionMcpAuth IPC channel and handler to trigger OAuth flow - Inject stored OAuth tokens as Authorization headers in buildRunTurnToolingConfig - Update McpAuthBanner with 'Authenticate in browser' button and loading state - Add tests for token store (7 tests) and token injection (3 tests) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -30,6 +30,7 @@ export function validateSessionToolingSelectionIds(
|
||||
export function buildRunTurnToolingConfig(
|
||||
tooling: WorkspaceToolingSettings,
|
||||
selection: SessionToolingSelection,
|
||||
tokenLookup?: (serverUrl: string) => string | undefined,
|
||||
): RunTurnToolingConfig | undefined {
|
||||
const mcpServersById = new Map<string, McpServerDefinition>(
|
||||
tooling.mcpServers.map((server) => [server.id, server]),
|
||||
@@ -68,7 +69,7 @@ export function buildRunTurnToolingConfig(
|
||||
tools: [...server.tools],
|
||||
timeoutMs: server.timeoutMs,
|
||||
url: server.url,
|
||||
headers: server.headers ? { ...server.headers } : undefined,
|
||||
headers: mergeAuthorizationHeader(server.url, server.headers, tokenLookup),
|
||||
},
|
||||
];
|
||||
});
|
||||
@@ -100,3 +101,19 @@ export function buildRunTurnToolingConfig(
|
||||
lspProfiles,
|
||||
};
|
||||
}
|
||||
|
||||
function mergeAuthorizationHeader(
|
||||
serverUrl: string,
|
||||
configHeaders: Record<string, string> | undefined,
|
||||
tokenLookup: ((serverUrl: string) => string | undefined) | undefined,
|
||||
): Record<string, string> | undefined {
|
||||
const bearerToken = tokenLookup?.(serverUrl);
|
||||
if (!bearerToken) {
|
||||
return configHeaders ? { ...configHeaders } : undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...(configHeaders ?? {}),
|
||||
Authorization: `Bearer ${bearerToken}`,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user