@@ -78,7 +78,7 @@ export interface OAuthClientProvider {
7878 *
7979 * Implementations must verify the resource matches the MCP server.
8080 */
81- validateProtectedResourceMetadata ? ( metadata ?: OAuthProtectedResourceMetadata ) : Promise < void > ;
81+ validateResourceURL ? ( serverUrl : string | URL , resource ?: string ) : Promise < URL | undefined > ;
8282}
8383
8484export type AuthResult = "AUTHORIZED" | "REDIRECT" ;
@@ -107,26 +107,19 @@ export async function auth(
107107 scope ?: string ;
108108 resourceMetadataUrl ?: URL } ) : Promise < AuthResult > {
109109
110- const resource = resourceUrlFromServerUrl ( typeof serverUrl === "string" ? new URL ( serverUrl ) : serverUrl ) ;
111-
112110 let resourceMetadata : OAuthProtectedResourceMetadata | undefined ;
113111 let authorizationServerUrl = serverUrl ;
114112 try {
115113 resourceMetadata = await discoverOAuthProtectedResourceMetadata ( serverUrl , { resourceMetadataUrl} ) ;
116- } catch ( error ) {
117- console . warn ( "Could not load OAuth Protected Resource metadata, falling back to /.well-known/oauth-authorization-server" , error )
118- }
119- if ( provider . validateProtectedResourceMetadata ) {
120- await provider . validateProtectedResourceMetadata ( resourceMetadata ) ;
121- } else if ( resourceMetadata ) {
122114 if ( resourceMetadata . authorization_servers && resourceMetadata . authorization_servers . length > 0 ) {
123115 authorizationServerUrl = resourceMetadata . authorization_servers [ 0 ] ;
124116 }
125- if ( resourceMetadata . resource !== resource . href ) {
126- throw new Error ( `Protected resource ${ resourceMetadata . resource } does not match expected ${ resource } ` ) ;
127- }
117+ } catch ( error ) {
118+ console . warn ( "Could not load OAuth Protected Resource metadata, falling back to /.well-known/oauth-authorization-server" , error )
128119 }
129120
121+ const resource : URL | undefined = await selectResourceURL ( serverUrl , provider , resourceMetadata ) ;
122+
130123 const metadata = await discoverOAuthMetadata ( authorizationServerUrl ) ;
131124
132125 // Handle client registration if needed
@@ -202,6 +195,19 @@ export async function auth(
202195 return "REDIRECT" ;
203196}
204197
198+ async function selectResourceURL ( serverUrl : string | URL , provider : OAuthClientProvider , resourceMetadata ?: OAuthProtectedResourceMetadata ) : Promise < URL | undefined > {
199+ if ( provider . validateResourceURL ) {
200+ return await provider . validateResourceURL ( serverUrl , resourceMetadata ?. resource ) ;
201+ }
202+
203+ const resource = resourceUrlFromServerUrl ( typeof serverUrl === "string" ? new URL ( serverUrl ) : serverUrl ) ;
204+ if ( resourceMetadata && resourceMetadata . resource !== resource . href ) {
205+ throw new Error ( `Protected resource ${ resourceMetadata . resource } does not match expected ${ resource } ` ) ;
206+ }
207+
208+ return resource ;
209+ }
210+
205211/**
206212 * Extract resource_metadata from response header.
207213 */
0 commit comments