Merge pull request #664 from modelcontextprotocol/pcarleton/auth-resource-validation2

[auth] adjust default validation for resource parameter in client flow, and server example
This commit is contained in:
Inna Harper 2025-06-20 08:54:12 +01:00 • committed by GitHub
commit 66b7cd2642
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,7 +2,7 @@ import pkceChallenge from "pkce-challenge";
import { LATEST_PROTOCOL_VERSION } from "../types.js";
import type { OAuthClientMetadata, OAuthClientInformation, OAuthTokens, OAuthMetadata, OAuthClientInformationFull, OAuthProtectedResourceMetadata } from "../shared/auth.js";
import { OAuthClientInformationFullSchema, OAuthMetadataSchema, OAuthProtectedResourceMetadataSchema, OAuthTokensSchema } from "../shared/auth.js";
import { resourceUrlFromServerUrl } from "../shared/auth-utils.js";
import { checkResourceAllowed, resourceUrlFromServerUrl } from "../shared/auth-utils.js";
/**
* Implements an end-to-end OAuth client to be used with one MCP server.
@ -197,14 +197,17 @@ export async function auth(
return "REDIRECT";
}
async function selectResourceURL(serverUrl: string| URL, provider: OAuthClientProvider, resourceMetadata?: OAuthProtectedResourceMetadata): Promise<URL | undefined> {
export async function selectResourceURL(serverUrl: string| URL, provider: OAuthClientProvider, resourceMetadata?: OAuthProtectedResourceMetadata): Promise<URL | undefined> {
let resource = resourceUrlFromServerUrl(serverUrl);
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 await provider.validateResourceURL(resource, resourceMetadata?.resource);
} else if (resourceMetadata) {
if (checkResourceAllowed({ requestedResource: resource, configuredResource: resourceMetadata.resource })) {
// If the resource mentioned in metadata is valid, prefer it since it is what the server is telling us to request.
resource = new URL(resourceMetadata.resource);
} else {
throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${resource} (or origin)`);
}
}
return resource;