Skip to content

fix: preserve exact OAuth resource indicators - #2581

Merged
KKonstantinov merged 4 commits into
modelcontextprotocol:mainfrom
hugosmoreira:fix/oauth-resource-indicator-preserve
Sep 3, 2026
Merged

fix: preserve exact OAuth resource indicators#2581
KKonstantinov merged 4 commits into
modelcontextprotocol:mainfrom
hugosmoreira:fix/oauth-resource-indicator-preserve

Conversation

@hugosmoreira

@hugosmoreira hugosmoreira commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • preserve the exact OAuth resource indicator published in protected resource metadata
  • continue validating the metadata value as a URL while avoiding URL.href normalization in authorization and token requests
  • accept either string or URL resource indicators in the exported OAuth request helpers
  • add regression coverage for authorization requests, token requests, and provider resource storage

Fixes #1968

Root cause

The default protected-resource flow converted the metadata's resource string to a URL and later serialized URL.href. For origin-only values such as https://resource.example.com, that serialization adds a trailing slash, which changes the OAuth resource indicator and can cause authorization servers to reject the request.

Custom provider validation remains unchanged: its returned URL is still used as the selected resource.

Validation

  • pnpm --filter @modelcontextprotocol/client typecheck
  • pnpm --filter @modelcontextprotocol/client build
  • pnpm --filter @modelcontextprotocol/client test — 798 tests passed
  • focused OAuth suite — 253 tests passed
  • scoped ESLint and Prettier checks on the changed files
  • repository-wide pre-push build and typecheck

Maintainer edit: Supersedes #1989, #1991, and #2518; the end-to-end pathless-PRM regression test and the changeset wording were adapted from #1991.

@changeset-bot

changeset-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: de24644

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@modelcontextprotocol/client Patch
@modelcontextprotocol/codemod Patch
@modelcontextprotocol/core Patch
@modelcontextprotocol/server-legacy Patch
@modelcontextprotocol/server Patch
@modelcontextprotocol/core-internal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@2581

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/@modelcontextprotocol/codemod@2581

@modelcontextprotocol/core

npm i https://pkg.pr.new/@modelcontextprotocol/core@2581

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@2581

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/@modelcontextprotocol/server-legacy@2581

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@2581

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@2581

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@2581

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@2581

commit: de24644

@hugosmoreira
hugosmoreira marked this pull request as ready for review July 30, 2026 17:12
@hugosmoreira
hugosmoreira requested a review from a team as a code owner July 30, 2026 17:12
@claude claude Bot added the v2 Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes label Aug 18, 2026
…sourceURL normalization (modelcontextprotocol#1968)

- auth.test.ts: drive auth() with PRM `resource: https://example.com` and assert the
  authorization redirect and the authorization-code token exchange both carry it
  without a trailing slash (fails on main with 'https://example.com/')
- auth.ts: JSDoc on selectResourceURL explaining that it returns a parsed URL and that
  auth() sends the metadata string verbatim; comment at the decision site in auth()
- changeset: describe the trailing-slash normalization, the Entra rejection, the
  widened `resource` inputs, and that selectResourceURL's signature is unchanged
@KKonstantinov

Copy link
Copy Markdown
Contributor

@claude review

KKonstantinov added a commit to MukundaKatta/typescript-sdk that referenced this pull request Sep 3, 2026
…resource string from auth() (modelcontextprotocol#1968)

Align the v1.x fix with the v2 shape (modelcontextprotocol#2581): the public signature of
selectResourceURL stays Promise<URL | undefined>; auth() sends the protected
resource metadata's `resource` string verbatim when the provider has no custom
validateResourceURL, and the OAuth helpers accept `string | URL` for `resource`
via a small resourceIndicatorToString serializer.

- auth.test.ts: the regression test now drives both the authorization redirect
  and the authorization-code token exchange with PRM `resource: https://example.com`
  and asserts neither gains a trailing slash; add a startAuthorization string case
- auth.ts: JSDoc on selectResourceURL and a comment at the decision site in auth()
- changeset: describe the normalization, the Entra rejection, the widened inputs,
  and that selectResourceURL's signature is unchanged
@KKonstantinov
KKonstantinov merged commit 5119ee7 into modelcontextprotocol:main Sep 3, 2026
15 checks passed
claude Bot pushed a commit that referenced this pull request Sep 4, 2026
Keep this branch's refreshAuthorization scope option and take main's
widened resource type (string | URL) from #2581. Client typecheck,
eslint, prettier and full test suite (884 tests) pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REWQAZGQACRjhFcxCX9g2P
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAuth resource indicator from protected resource metadata is normalized with a trailing slash

2 participants