Skip to content

fix(oauth): declare requested scopes in DCR body - #689

Merged
RhysSullivan merged 1 commit into
mainfrom
fix/oauth-dcr-scope-registration
May 6, 2026
Merged

fix(oauth): declare requested scopes in DCR body#689
RhysSullivan merged 1 commit into
mainfrom
fix/oauth-dcr-scope-registration

Conversation

@RhysSullivan

Copy link
Copy Markdown
Collaborator

Summary

When adding an MCP source backed by an Auth0-style authorization server (advertising scopes_supported that includes offline_access), the source-add flow fails after Dynamic Client Registration with:

/oauth/callback?error=invalid_scope&error_description=Client+was+not+registered+with+scope+offline_access

Trace evidence (one full attempt against an Auth0-shaped AS):

  1. GET /.well-known/oauth-protected-resource → 200
  2. GET /.well-known/oauth-authorization-server → 200 (advertises scopes_supported: ["openid", "profile", "email", "offline_access"])
  3. POST /register → 201 (DCR succeeds)
  4. Browser redirected to /authorize?...&scope=openid profile email offline_access
  5. Authorization server hits the configured callback with error=invalid_scope

Root cause

beginDynamicAuthorization in packages/core/sdk/src/oauth-discovery.ts computed the requested scope list after the DCR call and passed it only to buildAuthorizationUrl. The DCR body had no scope field, so RFC 7591 servers that strictly validate "client may only request scopes it registered with" rejected the subsequent /authorize redirect.

Fix

Compute scopes once before DCR, include it as scope: scopes.join(" ") in baseClientMetadata (only when non-empty, and still overridable by caller-supplied clientMetadata), and reuse the same value for the authorization URL.

Test plan

  • New test declares requested scopes in the DCR body so Auth0-style servers don't reject /authorize asserts the DCR request body contains scope: "openid profile email offline_access" and that the authorization URL carries the same scopes.
  • bunx vitest run packages/core/sdk/src/oauth-discovery.test.ts — 13/13 pass.
  • bun run typecheck — green.
  • bun run lint — green.
  • bun run format:check — green.

Auth0-style authorization servers (e.g. mcp.grata.com) reject /authorize
with invalid_scope when a dynamically-registered client requests scopes
it didn't declare at registration time. beginDynamicAuthorization now
passes the resolved scope list through to the DCR body.
@RhysSullivan
RhysSullivan merged commit b87fecc into main May 6, 2026
6 of 8 checks passed
RhysSullivan added a commit that referenced this pull request May 31, 2026
…ation

fix(oauth): declare requested scopes in DCR body
@RhysSullivan
RhysSullivan deleted the fix/oauth-dcr-scope-registration branch June 11, 2026 08:01
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.

1 participant