fix(oauth): use Protected Resource Metadata scopes in MCP DCR flow (#25958)

* fix(oauth): use Protected Resource Metadata scopes in MCP DCR flow

The Dynamic Client Registration flow seeded the registration request
`scope` from the Authorization Server's `scopes_supported` (RFC 8414),
which is a full catalog of every scope the AS can grant across all
resources. Per RFC 9728 and the MCP Scope Selection Strategy, the
resource-specific Protected Resource Metadata `scopes_supported` is the
correct, least-privilege source.

The PRM is already fetched in this function; this change prefers its
`scopes_supported` and keeps the AS `scopes_supported` only as a
fallback when the PRM advertises none. Mirrors the static-credentials
fix in #24690.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(oauth): trim DCR scope comment per review feedback

Shortens the inline comment per review feedback on #25958.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jamie Lin
2026-06-16 23:53:38 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 087878ce84
commit ec86ce5cf7
+7
View File
@@ -435,6 +435,13 @@ async def get_oauth_client_info_with_dynamic_client_registration(
# Attempt to fetch OAuth server metadata to get registration endpoint & scopes
resource_metadata = await get_protected_resource_metadata(oauth_server_url)
resource = resource_metadata.resource
# Prefer the resource-specific scopes from the Protected Resource Metadata
# (RFC 9728) over the AS's full scopes_supported catalog, for least
# privilege. Mirrors the static-credentials flow (#24690).
if resource_metadata.scopes_supported:
oauth_client_metadata.scope = ' '.join(resource_metadata.scopes_supported)
discovery_urls = resource_metadata.get_discovery_urls(oauth_server_url)
for url in discovery_urls:
async with aiohttp.ClientSession(trust_env=True) as session: