From ec86ce5cf735a1a064d8963d18bb44a61c3728e0 Mon Sep 17 00:00:00 2001 From: Jamie Lin Date: Wed, 17 Jun 2026 05:53:38 +0800 Subject: [PATCH] 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) * 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) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- backend/open_webui/utils/oauth.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index f2e1aa14f6..dfddd487e4 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -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: