Uh oh!
There was an error while loading. Please reload this page.
feat: Add support for separate Authorization Server / Resource server in server flow (spec: DRAFT-2025-v2) - #503
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| it("should include resource_metadata in WWW-Authenticate header when token verification fails", async () => { | ||
| mockRequest.headers = { | ||
| authorization: "Bearer invalid-token", |
Check failure
Code scanning / CodeQL
Hard-coded credentials
| it("should include resource_metadata in WWW-Authenticate header for insufficient scope errors", async () => { | ||
| mockRequest.headers = { | ||
| authorization: "Bearer valid-token", |
Check failure
Code scanning / CodeQL
Hard-coded credentials
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| it("should not affect server errors (no WWW-Authenticate header)", async () => { | ||
| mockRequest.headers = { | ||
| authorization: "Bearer valid-token", |
Check failure
Code scanning / CodeQL
Hard-coded credentials
Uh oh!
There was an error while loading. Please reload this page.
| /** | ||
| * Simple in-memory implementation of OAuth clients store for demo purposes. | ||
| * In production, this should be backed by a persistent database. | ||
| */ |
There was a problem hiding this comment.
Maybe emphasising a bit more this is a demo
| /** | |
| *Simplein-memoryimplementationofOAuthclientsstorefordemopurposes. | |
| *Inproduction,thisshouldbebackedbyapersistentdatabase. | |
| */ | |
| /** | |
| *🚨DEMOONLY-NOTFORPRODUCTION | |
| * | |
| *ThisexampledemonstratesMCPOAuthflowbutlackssomeofthefeaturesrequiredforproductionuse: | |
| *-Separateauth/resourceservers | |
| *-PKCEvalidation | |
| *-Persistenttokenstorage | |
| *-Ratelimiting |
There was a problem hiding this comment.
sg, although this does support PKCE (see below) and separate AS / RS. This is intended to be a standalone AS.
| provider, | ||
| issuerUrl: authServerUrl, | ||
| scopesSupported: ['mcp:tools'], | ||
| // This endpoint is set up on the Authorization server, but really shouldn't be. |
There was a problem hiding this comment.
maybe add a link to the spec and explanation this is only for demo
There was a problem hiding this comment.
yea let me see about re-working this... we should make it easier to provide just the backwards-compat endpoint
| import { DemoInMemoryAuthProvider } from './demoInMemoryOAuthProvider.js'; | ||
| // Check for OAuth flag | ||
| const useOAuth = process.argv.includes('--oauth'); |
There was a problem hiding this comment.
worth adding to README in src/examples/README.md as I just copy-pasted command and forgot to add it 🙈
| }; | ||
| mockVerifyAccessToken.mockResolvedValue(expiredAuthInfo); | ||
| mockRequest.headers = { |
Check failure
Code scanning / CodeQL
Hard-coded credentials
| }; | ||
| mockVerifyAccessToken.mockResolvedValue(authInfo); | ||
| mockRequest.headers = { |
Check failure
Code scanning / CodeQL
Hard-coded credentials
pcarleton
left a comment
There was a problem hiding this comment.
Okay, had to do a bit of an overhaul, and then refactored to hopefully make things simpler.
Changes:
- There's now a single metadata router, that the "all-in-one" flow (
mcpAuthRouter) uses, and can be used by a separate-as-rs flow viamcpAuthMetadataRouter. - This router now takes an OAuthMetadata instance as would be returned by an Authorization Server. This matches the expected flow of having a stanadlone authorization server, getting its metadata, and then advertising it on the server. For backwards compatibility, it will just re-advertise the AS's metadata on the well-known endpoint.
- The bearer middleware now takes a
OAuthTokenVerifierwhich requires only 1 function instead of a full provider, since that's all you need on the MCP server in a "separate-as-rs" implementation.
Uh oh!
There was an error while loading. Please reload this page.
| /** | ||
| * Simple in-memory implementation of OAuth clients store for demo purposes. | ||
| * In production, this should be backed by a persistent database. | ||
| */ |
There was a problem hiding this comment.
sg, although this does support PKCE (see below) and separate AS / RS. This is intended to be a standalone AS.
| provider, | ||
| issuerUrl: authServerUrl, | ||
| scopesSupported: ['mcp:tools'], | ||
| // This endpoint is set up on the Authorization server, but really shouldn't be. |
There was a problem hiding this comment.
yea let me see about re-working this... we should make it easier to provide just the backwards-compat endpoint
…t-layout Make prompt layout consistent
Motivation and Context
This adds support for RFC 9728 (Protected Resource Metadata) in line with the latest draft spec https://modelcontextprotocol.io/specification/draft/basic/authorization#2-3-1-authorization-server-location
How Has This Been Tested?
Breaking Changes
This change should be strictly additive, adding an additional metadata endpoint, and extra information to the
WWW-Authenticateheaders.Types of changes
Checklist
Additional context
there is another PR that implements the client side of this here:
#416