This commit is contained in:
Timothy Jaeryang Baek
2026-06-22 14:42:23 +02:00
parent 928eb015bd
commit 88901bfa04
3 changed files with 49 additions and 2 deletions

View File

@@ -228,6 +228,7 @@ from open_webui.utils.oauth import (
encrypt_data,
get_oauth_client_info_with_dynamic_client_registration,
get_oauth_client_info_with_static_credentials,
recover_static_oauth_client_metadata,
resolve_oauth_client_info,
)
from open_webui.utils.plugin import install_tool_and_function_dependencies
@@ -535,6 +536,9 @@ async def initialize_runtime_config(app: FastAPI):
if server_id and auth_type in ('oauth_2.1', 'oauth_2.1_static'):
try:
oauth_client_info = resolve_oauth_client_info(tool_server_connection)
oauth_client_info = await recover_static_oauth_client_metadata(
tool_server_connection, oauth_client_info
)
app.state.oauth_client_manager.add_client(
f'mcp:{server_id}',
OAuthClientInformationFull(**oauth_client_info),

View File

@@ -21,6 +21,7 @@ from open_webui.utils.oauth import (
get_discovery_urls,
get_oauth_client_info_with_dynamic_client_registration,
get_oauth_client_info_with_static_credentials,
recover_static_oauth_client_metadata,
resolve_oauth_client_info,
)
from open_webui.utils.tools import (
@@ -241,6 +242,9 @@ async def set_tool_servers_config(
if auth_type in ('oauth_2.1', 'oauth_2.1_static') and server_id:
try:
oauth_client_info = resolve_oauth_client_info(connection)
oauth_client_info = await recover_static_oauth_client_metadata(
connection, oauth_client_info
)
request.app.state.oauth_client_manager.add_client(
f'{server_type}:{server_id}',
OAuthClientInformationFull(**oauth_client_info),

View File

@@ -666,6 +666,34 @@ def resolve_oauth_client_info(connection: dict) -> dict:
return data
async def recover_static_oauth_client_metadata(connection: dict, oauth_client_info: dict) -> dict:
if connection.get('auth_type') != 'oauth_2.1_static':
return oauth_client_info
if oauth_client_info.get('scope') and oauth_client_info.get('resource'):
return oauth_client_info
server_url = connection.get('url')
if not server_url:
return oauth_client_info
try:
resource_metadata = await get_protected_resource_metadata(server_url)
except Exception as e:
log.debug(f'Unable to recover static OAuth metadata for {server_url}: {e}')
return oauth_client_info
recovered = {**oauth_client_info}
if not recovered.get('scope') and resource_metadata.scopes_supported:
recovered['scope'] = ' '.join(resource_metadata.scopes_supported)
log.info(f'Recovered static OAuth scopes for {server_url} from protected resource metadata')
if not recovered.get('resource') and resource_metadata.resource:
recovered['resource'] = resource_metadata.resource
return recovered
class OAuthClientManager:
def __init__(self, app):
self.oauth = OAuth()
@@ -744,6 +772,9 @@ class OAuthClientManager:
try:
oauth_client_info = resolve_oauth_client_info(connection)
oauth_client_info = await recover_static_oauth_client_metadata(
connection, oauth_client_info
)
return self.add_client(expected_client_id, OAuthClientInformationFull(**oauth_client_info))['client']
except Exception as e:
log.error(f'Failed to lazily add OAuth client {expected_client_id} from config: {e}')
@@ -777,7 +808,13 @@ class OAuthClientManager:
redirect_uri = str(client_info.redirect_uris[0])
try:
auth_data = await client.create_authorization_url(redirect_uri=redirect_uri)
kwargs = {}
if client_info.scope:
kwargs['scope'] = client_info.scope
if client_info.resource:
kwargs['resource'] = client_info.resource
auth_data = await client.create_authorization_url(redirect_uri=redirect_uri, **kwargs)
authorization_url = auth_data.get('url')
if not authorization_url:
@@ -1013,8 +1050,10 @@ class OAuthClientManager:
redirect_uri = client_info.redirect_uris[0] if client_info.redirect_uris else None
redirect_uri_str = str(redirect_uri) if redirect_uri else None
# RFC 8707: pass resource indicator so the IdP sets the correct JWT audience
# Pass explicit scope/resource parameters for providers that require them.
kwargs = {}
if client_info.scope:
kwargs['scope'] = client_info.scope
if client_info.resource:
kwargs['resource'] = client_info.resource
return await client.authorize_redirect(request, redirect_uri_str, **kwargs)