Skip to content

fix(auth): make 2025-03-26 backcompat mock RFC 8414 §3.3-compliant#359

Merged
pcarleton merged 2 commits into
mainfrom
fweinberger/fix-march-backcompat-issuer-mismatch
Jun 23, 2026
Merged

fix(auth): make 2025-03-26 backcompat mock RFC 8414 §3.3-compliant#359
pcarleton merged 2 commits into
mainfrom
fweinberger/fix-march-backcompat-issuer-mismatch

Conversation

@felixweinberger

Copy link
Copy Markdown
Collaborator

The auth/2025-03-26-oauth-metadata-backcompat scenario tests that an MCP client can still discover and authenticate when the server uses the March 2025 spec layout: no Protected Resource Metadata, OAuth Authorization Server Metadata served at the root /.well-known/oauth-authorization-server. That property is still worth testing in --suite all.

The mock's configuration has a latent bug unrelated to that property: it passes routePrefix: '/oauth', which makes createAuthServer report issuer: '<origin>/oauth' in the metadata while serving that metadata at the root well-known path. RFC 8414 §3.3 requires that "the issuer value returned MUST be identical to the authorization server's issuer identifier value into which the well-known URI string was inserted" — i.e., metadata served at the root well-known path must have issuer: '<origin>' with no path component. A real March-2025-era authorization server following RFC 8414 (published 2018) would have been compliant; the mismatch here is an artifact of how routePrefix and the default metadataPath interact.

This was invisible until SEP-2468 made the §3.3 check a client MUST in the 2026-07-28 spec (authorization-server-discovery.mdx: "the issuer value in the document MUST be identical to the issuer identifier used to construct the well-known URL. If they differ, the client MUST NOT use the metadata"). A client implementing that MUST now correctly rejects the mock's metadata, so the scenario and SEP-2468 cannot both pass as written.

Motivation and Context

Dropping routePrefix makes the mock §3.3-compliant without changing what the scenario tests. The route prefix existed to avoid collisions with the MCP server routes, but createServer only mounts /mcp (and the PRM path, which is null here), so unprefixed /authorize, /token, /register are fine — the sibling auth/2025-03-26-oauth-endpoint-fallback scenario in the same file already mounts them at root.

How Has This Been Tested?

CI will verify; local npm ci was blocked by registry access in my environment. The change is a single options-property removal.

Breaking Changes

None — fixes a mock configuration bug; no API or behavior change for clients that don't enforce §3.3.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Surfaced while landing SEP-2468 in typescript-sdk: with §3.3 default-on, this is the only auth/* scenario that regresses, and only because of the mock's issuer/well-known mismatch.

Drop the routePrefix from auth/2025-03-26-oauth-metadata-backcompat. The
prefix caused createAuthServer to report issuer:'<origin>/oauth' while
serving the metadata at the root /.well-known/oauth-authorization-server —
an RFC 8414 §3.3 mismatch a conforming client must reject. The MCP server
in this scenario only mounts /mcp, so the unprefixed /authorize, /token,
/register routes do not collide (the sibling endpoint-fallback scenario
already mounts them at root).

The scenario continues to test exactly what it's meant to: 2025-03-26-spec
discovery with no PRM, OAuth metadata at the root well-known path.
@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@modelcontextprotocol/conformance@359

commit: 7640176

…er instead

Dropping routePrefix made the metadata-advertised endpoints land on the
2025-03-26 hardcoded fallback paths, so a client that fetches the
well-known doc but ignores its body would now pass. Restore the prefix
and pin the metadata issuer to the bare origin via a lazy
metadataIssuer override so the mock is RFC 8414 §3.3-compliant without
losing the fallback-vs-metadata distinction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants