From dada5f66f570f312a910bae095c481915b2f80c4 Mon Sep 17 00:00:00 2001 From: Paul Carleton Date: Wed, 18 Jun 2025 15:52:56 +0100 Subject: [PATCH] wip helper func --- src/client/auth.ts | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/client/auth.ts b/src/client/auth.ts index 4d604d28..bef7965f 100644 --- a/src/client/auth.ts +++ b/src/client/auth.ts @@ -78,7 +78,7 @@ export interface OAuthClientProvider { * * Implementations must verify the resource matches the MCP server. */ - validateProtectedResourceMetadata?(metadata?: OAuthProtectedResourceMetadata): Promise; + validateResourceURL?(serverUrl: string | URL, resource?: string): Promise; } export type AuthResult = "AUTHORIZED" | "REDIRECT"; @@ -107,26 +107,19 @@ export async function auth( scope?: string; resourceMetadataUrl?: URL }): Promise { - const resource = resourceUrlFromServerUrl(typeof serverUrl === "string" ? new URL(serverUrl) : serverUrl); - let resourceMetadata: OAuthProtectedResourceMetadata | undefined; let authorizationServerUrl = serverUrl; try { resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, {resourceMetadataUrl}); - } catch (error) { - console.warn("Could not load OAuth Protected Resource metadata, falling back to /.well-known/oauth-authorization-server", error) - } - if (provider.validateProtectedResourceMetadata) { - await provider.validateProtectedResourceMetadata(resourceMetadata); - } else if (resourceMetadata) { if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) { authorizationServerUrl = resourceMetadata.authorization_servers[0]; } - if (resourceMetadata.resource !== resource.href) { - throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${resource}`); - } + } catch (error) { + console.warn("Could not load OAuth Protected Resource metadata, falling back to /.well-known/oauth-authorization-server", error) } + const resource: URL | undefined = await selectResourceURL(serverUrl, provider, resourceMetadata); + const metadata = await discoverOAuthMetadata(authorizationServerUrl); // Handle client registration if needed @@ -202,6 +195,19 @@ export async function auth( return "REDIRECT"; } +async function selectResourceURL(serverUrl: string| URL, provider: OAuthClientProvider, resourceMetadata?: OAuthProtectedResourceMetadata): Promise { + if (provider.validateResourceURL) { + return await provider.validateResourceURL(serverUrl, resourceMetadata?.resource); + } + + const resource = resourceUrlFromServerUrl(typeof serverUrl === "string" ? new URL(serverUrl) : serverUrl); + if (resourceMetadata && resourceMetadata.resource !== resource.href) { + throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${resource}`); + } + + return resource; +} + /** * Extract resource_metadata from response header. */