This commit is contained in:
Olivier Chafik 2025-06-18 11:23:09 +01:00
commit bf72f87788
No known key found for this signature in database
5 changed files with 9 additions and 20 deletions

View file

@ -78,7 +78,7 @@ npx tsx src/examples/server/simpleStreamableHttp.ts
npx tsx src/examples/server/simpleStreamableHttp.ts --oauth
# To mitigate impersonation risks, enable strict Resource Identifier verification:
npx tsx src/examples/server/simpleStreamableHttp.ts --oauth --oauth-resource=https://some-mcp-server.com --oauth-resource-strict
npx tsx src/examples/server/simpleStreamableHttp.ts --oauth --oauth-strict
```
##### JSON Response Mode Server

View file

@ -102,7 +102,7 @@ export class DemoInMemoryAuthProvider implements OAuthServerProvider {
}
if (this.validateResource && !this.validateResource(codeData.params.resource)) {
throw new Error('Invalid resource');
throw new Error(`Invalid resource: ${codeData.params.resource}`);
}
this.codes.delete(authorizationCode);

View file

@ -12,13 +12,7 @@ import { OAuthMetadata } from 'src/shared/auth.js';
// Check for OAuth flag
const useOAuth = process.argv.includes('--oauth');
// Resource Indicator the OAuth tokens are checked against (RFC8707).
const expectedOAuthResource = (iArg => iArg < 0 ? undefined: process.argv[iArg + 1])(process.argv.indexOf('--oauth-resource'));
// Requires Resource Indicator check (implies protocol more recent than 2025-03-26)
const strictOAuthResourceCheck = process.argv.includes('--oauth-resource-strict');
if (strictOAuthResourceCheck && !expectedOAuthResource) {
throw new Error(`Strict resource indicator checking requires passing the expected resource with --oauth-resource https://...`);
}
const strictOAuth = process.argv.includes('--oauth-strict');
// Create an MCP server with implementation details
const getServer = () => {
@ -292,7 +286,7 @@ if (useOAuth) {
const oauthMetadata: OAuthMetadata = setupAuthServer(authServerUrl, mcpServerUrl);
const tokenVerifier = {
verifyAccessToken: async (token: string, protocolVersion: string) => {
verifyAccessToken: async (token: string) => {
const endpoint = oauthMetadata.introspection_endpoint;
if (!endpoint) {
@ -316,11 +310,11 @@ if (useOAuth) {
const data = await response.json();
if (expectedOAuthResource) {
if (strictOAuthResourceCheck && !data.resource) {
if (strictOAuth) {
if (!data.resource) {
throw new Error('Resource Indicator (RFC8707) missing');
}
if (data.resource && data.resource !== expectedOAuthResource) {
if (data.resource !== expectedOAuthResource) {
throw new Error(`Expected resource indicator ${expectedOAuthResource}, got: ${data.resource}`);
}
}

View file

@ -51,12 +51,7 @@ export function requireBearerAuth({ verifier, requiredScopes = [], resourceMetad
throw new InvalidTokenError("Invalid Authorization header format, expected 'Bearer TOKEN'");
}
let protocolVersion = req.headers["mcp-protocol-version"] ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
if (Array.isArray(protocolVersion)) {
protocolVersion = protocolVersion[protocolVersion.length - 1];
}
const authInfo = await verifier.verifyAccessToken(token, protocolVersion);
const authInfo = await verifier.verifyAccessToken(token);
// Check if token has the required scopes (if any)
if (requiredScopes.length > 0) {

View file

@ -80,5 +80,5 @@ export interface OAuthTokenVerifier {
/**
* Verifies an access token and returns information about it.
*/
verifyAccessToken(token: string, protocolVersion: string): Promise<AuthInfo>;
verifyAccessToken(token: string): Promise<AuthInfo>;
}