UNPKG

buroventures-harald-code-core

Version:

Harald Code Core - Core functionality for AI-powered coding assistant

183 lines 7.39 kB
/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { getErrorMessage } from '../utils/errors.js'; /** * Utility class for common OAuth operations. */ export class OAuthUtils { /** * Construct well-known OAuth endpoint URLs. */ static buildWellKnownUrls(baseUrl) { const serverUrl = new URL(baseUrl); const base = `${serverUrl.protocol}//${serverUrl.host}`; return { protectedResource: new URL('/.well-known/oauth-protected-resource', base).toString(), authorizationServer: new URL('/.well-known/oauth-authorization-server', base).toString(), }; } /** * Fetch OAuth protected resource metadata. * * @param resourceMetadataUrl The protected resource metadata URL * @returns The protected resource metadata or null if not available */ static async fetchProtectedResourceMetadata(resourceMetadataUrl) { try { const response = await fetch(resourceMetadataUrl); if (!response.ok) { return null; } return (await response.json()); } catch (error) { console.debug(`Failed to fetch protected resource metadata from ${resourceMetadataUrl}: ${getErrorMessage(error)}`); return null; } } /** * Fetch OAuth authorization server metadata. * * @param authServerMetadataUrl The authorization server metadata URL * @returns The authorization server metadata or null if not available */ static async fetchAuthorizationServerMetadata(authServerMetadataUrl) { try { const response = await fetch(authServerMetadataUrl); if (!response.ok) { return null; } return (await response.json()); } catch (error) { console.debug(`Failed to fetch authorization server metadata from ${authServerMetadataUrl}: ${getErrorMessage(error)}`); return null; } } /** * Convert authorization server metadata to OAuth configuration. * * @param metadata The authorization server metadata * @returns The OAuth configuration */ static metadataToOAuthConfig(metadata) { return { authorizationUrl: metadata.authorization_endpoint, tokenUrl: metadata.token_endpoint, scopes: metadata.scopes_supported || [], }; } /** * Discover OAuth configuration using the standard well-known endpoints. * * @param serverUrl The base URL of the server * @returns The discovered OAuth configuration or null if not available */ static async discoverOAuthConfig(serverUrl) { try { const wellKnownUrls = this.buildWellKnownUrls(serverUrl); // First, try to get the protected resource metadata const resourceMetadata = await this.fetchProtectedResourceMetadata(wellKnownUrls.protectedResource); if (resourceMetadata?.authorization_servers?.length) { // Use the first authorization server const authServerUrl = resourceMetadata.authorization_servers[0]; const authServerMetadataUrl = new URL('/.well-known/oauth-authorization-server', authServerUrl).toString(); const authServerMetadata = await this.fetchAuthorizationServerMetadata(authServerMetadataUrl); if (authServerMetadata) { const config = this.metadataToOAuthConfig(authServerMetadata); if (authServerMetadata.registration_endpoint) { console.log('Dynamic client registration is supported at:', authServerMetadata.registration_endpoint); } return config; } } // Fallback: try /.well-known/oauth-authorization-server at the base URL console.debug(`Trying OAuth discovery fallback at ${wellKnownUrls.authorizationServer}`); const authServerMetadata = await this.fetchAuthorizationServerMetadata(wellKnownUrls.authorizationServer); if (authServerMetadata) { const config = this.metadataToOAuthConfig(authServerMetadata); if (authServerMetadata.registration_endpoint) { console.log('Dynamic client registration is supported at:', authServerMetadata.registration_endpoint); } return config; } return null; } catch (error) { console.debug(`Failed to discover OAuth configuration: ${getErrorMessage(error)}`); return null; } } /** * Parse WWW-Authenticate header to extract OAuth information. * * @param header The WWW-Authenticate header value * @returns The resource metadata URI if found */ static parseWWWAuthenticateHeader(header) { // Parse Bearer realm and resource_metadata const match = header.match(/resource_metadata="([^"]+)"/); if (match) { return match[1]; } return null; } /** * Discover OAuth configuration from WWW-Authenticate header. * * @param wwwAuthenticate The WWW-Authenticate header value * @returns The discovered OAuth configuration or null if not available */ static async discoverOAuthFromWWWAuthenticate(wwwAuthenticate) { const resourceMetadataUri = this.parseWWWAuthenticateHeader(wwwAuthenticate); if (!resourceMetadataUri) { return null; } console.log(`Found resource metadata URI from www-authenticate header: ${resourceMetadataUri}`); const resourceMetadata = await this.fetchProtectedResourceMetadata(resourceMetadataUri); if (!resourceMetadata?.authorization_servers?.length) { return null; } const authServerUrl = resourceMetadata.authorization_servers[0]; const authServerMetadataUrl = new URL('/.well-known/oauth-authorization-server', authServerUrl).toString(); const authServerMetadata = await this.fetchAuthorizationServerMetadata(authServerMetadataUrl); if (authServerMetadata) { console.log('OAuth configuration discovered successfully from www-authenticate header'); return this.metadataToOAuthConfig(authServerMetadata); } return null; } /** * Extract base URL from an MCP server URL. * * @param mcpServerUrl The MCP server URL * @returns The base URL */ static extractBaseUrl(mcpServerUrl) { const serverUrl = new URL(mcpServerUrl); return `${serverUrl.protocol}//${serverUrl.host}`; } /** * Check if a URL is an SSE endpoint. * * @param url The URL to check * @returns True if the URL appears to be an SSE endpoint */ static isSSEEndpoint(url) { return url.includes('/sse') || !url.includes('/mcp'); } /** * Build a resource parameter for OAuth requests. * * @param endpointUrl The endpoint URL * @returns The resource parameter value */ static buildResourceParameter(endpointUrl) { const url = new URL(endpointUrl); return `${url.protocol}//${url.host}`; } } //# sourceMappingURL=oauth-utils.js.map