Skip to content

fix(auth): callback iss must equal metadata issuer (honor metadataIssuer override)#361

Merged
pcarleton merged 1 commit into
mainfrom
fweinberger/auth-backcompat-callback-iss
Jun 24, 2026
Merged

fix(auth): callback iss must equal metadata issuer (honor metadataIssuer override)#361
pcarleton merged 1 commit into
mainfrom
fweinberger/auth-backcompat-callback-iss

Conversation

@felixweinberger

Copy link
Copy Markdown
Collaborator

The mock AS's authorization-response iss and its published metadata issuer are the same identifier by definition (RFC 9207 §2: "the authorization server's issuer identifier ... MUST be identical to the value in the issuer field of the authorization server metadata"). RFC 9207 §2.4 then requires clients to compare the received iss against the metadata issuer via simple string comparison and reject on any difference.

createAuthServer derived these two values independently:

So a scenario that sets metadataIssuer (to satisfy RFC 8414 §3.3) while keeping a routePrefix — exactly what auth/2025-03-26-oauth-metadata-backcompat does after #359 — produces a mock whose callback iss doesn't match its own metadata. An RFC 9207-conforming client correctly rejects it, and the scenario becomes un-passable for the wrong reason.

This extracts a single resolveIssuer() and uses it for both the metadata issuer and the 'correct'/'normalized' callback iss, so they're identical by construction. Scenarios that want a deliberate mismatch already use issInRedirect: 'wrong', which is unchanged.

Motivation and Context

Follow-up to #359. Surfaced by typescript-sdk#2344 turning RFC 9207 validation default-on: IssuerMismatchError: expected "http://localhost:45193", received "http://localhost:45193/oauth".

How Has This Been Tested?

Ran auth/2025-03-26-oauth-metadata-backcompat against typescript-sdk at the SEP-2468 head; passes with this change (fails without). Existing iss-* scenarios unaffected (they don't set metadataIssuer, so resolveIssuer() falls through to the original derivation).

Breaking Changes

None — resolveIssuer() returns exactly what each call site computed before when metadataIssuer is unset.

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

Once this lands in a published release, typescript-sdk can drop the auth/2025-03-26-oauth-metadata-backcompat expected-failure entry.

…uer override)

#359 made the metadata `issuer` honor the metadataIssuer override so the
2025-03-26 backcompat scenario is RFC 8414 §3.3-compliant. The authorize
callback's `iss` parameter was still derived as `getAuthBaseUrl()+routePrefix`,
so when a scenario sets metadataIssuer (bare origin) but keeps a routePrefix,
the callback `iss` mismatches the metadata `issuer` and an RFC 9207-conforming
client correctly rejects it.

Extract `resolveIssuer()` and use it for both the metadata `issuer` and the
`'correct'`/`'normalized'` callback `iss` so they always match.
@pkg-pr-new

pkg-pr-new Bot commented Jun 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 8a6fcba

@pcarleton pcarleton merged commit 5d1b3ce into main Jun 24, 2026
8 checks passed
@pcarleton pcarleton deleted the fweinberger/auth-backcompat-callback-iss branch June 24, 2026 10:30
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