refac
This commit is contained in:
@@ -8,6 +8,7 @@ from typing import Optional
|
||||
|
||||
from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.headers import get_custom_headers
|
||||
from open_webui.config import get_config, save_config, async_save_config
|
||||
from open_webui.config import BannerModel
|
||||
|
||||
@@ -103,6 +104,7 @@ class OAuthClientRegistrationForm(BaseModel):
|
||||
client_id: str
|
||||
client_name: Optional[str] = None
|
||||
client_secret: Optional[str] = None
|
||||
oauth_server_url: Optional[str] = None
|
||||
|
||||
|
||||
@router.post('/oauth/clients/register')
|
||||
@@ -117,18 +119,20 @@ async def register_oauth_client(
|
||||
if type:
|
||||
oauth_client_id = f'{type}:{form_data.client_id}'
|
||||
|
||||
oauth_server_url = form_data.oauth_server_url if form_data.oauth_server_url else form_data.url
|
||||
|
||||
if form_data.client_secret:
|
||||
# Static credentials: skip dynamic registration, build from provided credentials
|
||||
oauth_client_info = await get_oauth_client_info_with_static_credentials(
|
||||
request,
|
||||
oauth_client_id,
|
||||
form_data.url,
|
||||
oauth_server_url,
|
||||
oauth_client_id=form_data.client_id,
|
||||
oauth_client_secret=form_data.client_secret,
|
||||
)
|
||||
else:
|
||||
oauth_client_info = await get_oauth_client_info_with_dynamic_client_registration(
|
||||
request, oauth_client_id, form_data.url
|
||||
request, oauth_client_id, oauth_server_url
|
||||
)
|
||||
return {
|
||||
'status': True,
|
||||
@@ -155,6 +159,7 @@ class ToolServerConnection(BaseModel):
|
||||
headers: Optional[dict | str] = None
|
||||
key: Optional[str]
|
||||
config: Optional[dict]
|
||||
info: Optional[dict] = None
|
||||
|
||||
model_config = ConfigDict(extra='allow')
|
||||
|
||||
@@ -369,7 +374,8 @@ async def verify_tool_servers_config(request: Request, form_data: ToolServerConn
|
||||
try:
|
||||
if form_data.type == 'mcp':
|
||||
if form_data.auth_type in ('oauth_2.1', 'oauth_2.1_static'):
|
||||
discovery_urls = await get_discovery_urls(form_data.url)
|
||||
oauth_server_url = form_data.info.get('oauth_server_url') if form_data.info and form_data.info.get('oauth_server_url') else form_data.url
|
||||
discovery_urls = await get_discovery_urls(oauth_server_url)
|
||||
for discovery_url in discovery_urls:
|
||||
log.debug(f'Trying to fetch OAuth 2.1 discovery document from {discovery_url}')
|
||||
async with aiohttp.ClientSession(
|
||||
@@ -428,7 +434,8 @@ async def verify_tool_servers_config(request: Request, form_data: ToolServerConn
|
||||
if form_data.headers and isinstance(form_data.headers, dict):
|
||||
if headers is None:
|
||||
headers = {}
|
||||
headers.update(form_data.headers)
|
||||
custom_headers = get_custom_headers(form_data.headers, user)
|
||||
headers.update(custom_headers)
|
||||
|
||||
await client.connect(form_data.url, headers=headers)
|
||||
specs = await client.list_tool_specs()
|
||||
@@ -472,7 +479,8 @@ async def verify_tool_servers_config(request: Request, form_data: ToolServerConn
|
||||
if form_data.headers and isinstance(form_data.headers, dict):
|
||||
if headers is None:
|
||||
headers = {}
|
||||
headers.update(form_data.headers)
|
||||
custom_headers = get_custom_headers(form_data.headers, user)
|
||||
headers.update(custom_headers)
|
||||
|
||||
url = get_tool_server_url(form_data.url, form_data.path)
|
||||
return await get_tool_server_data(url, headers=headers)
|
||||
|
||||
@@ -62,7 +62,7 @@ from open_webui.utils.session_pool import (
|
||||
)
|
||||
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.headers import include_user_info_headers
|
||||
from open_webui.utils.headers import include_user_info_headers, get_custom_headers
|
||||
from open_webui.utils.anthropic import is_anthropic_url, get_anthropic_models
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -215,7 +215,8 @@ async def get_headers_and_cookies(
|
||||
headers['Authorization'] = f'Bearer {token}'
|
||||
|
||||
if config.get('headers') and isinstance(config.get('headers'), dict):
|
||||
headers = {**headers, **config.get('headers')}
|
||||
custom_headers = get_custom_headers(config.get('headers'), user, metadata)
|
||||
headers.update(custom_headers)
|
||||
|
||||
return headers, cookies
|
||||
|
||||
|
||||
@@ -16,3 +16,25 @@ def include_user_info_headers(headers, user):
|
||||
FORWARD_USER_INFO_HEADER_USER_EMAIL: user.email,
|
||||
FORWARD_USER_INFO_HEADER_USER_ROLE: user.role,
|
||||
}
|
||||
|
||||
def get_custom_headers(custom_headers: dict, user=None, metadata: dict = None) -> dict:
|
||||
if not custom_headers or not isinstance(custom_headers, dict):
|
||||
return {}
|
||||
|
||||
metadata = metadata or {}
|
||||
template_vars = {
|
||||
'{{CHAT_ID}}': metadata.get('chat_id', '') or '',
|
||||
'{{MESSAGE_ID}}': metadata.get('message_id', '') or '',
|
||||
'{{USER_ID}}': (user.id if user else '') or '',
|
||||
'{{USER_NAME}}': (user.name if user else '') or '',
|
||||
}
|
||||
|
||||
parsed_headers = {}
|
||||
for key, value in custom_headers.items():
|
||||
if not isinstance(value, str):
|
||||
value = str(value)
|
||||
for token, val in template_vars.items():
|
||||
value = value.replace(token, val)
|
||||
parsed_headers[key] = value
|
||||
|
||||
return parsed_headers
|
||||
|
||||
@@ -54,7 +54,7 @@ from open_webui.env import (
|
||||
FORWARD_SESSION_INFO_HEADER_MESSAGE_ID,
|
||||
REDIS_KEY_PREFIX,
|
||||
)
|
||||
from open_webui.utils.headers import include_user_info_headers
|
||||
from open_webui.utils.headers import include_user_info_headers, get_custom_headers
|
||||
from open_webui.tools.builtin import (
|
||||
search_web,
|
||||
fetch_url,
|
||||
@@ -337,8 +337,9 @@ async def get_tools(request: Request, tool_ids: list[str], user: UserModel, extr
|
||||
|
||||
connection_headers = tool_server_connection.get('headers', None)
|
||||
if connection_headers and isinstance(connection_headers, dict):
|
||||
for key, value in connection_headers.items():
|
||||
headers[key] = value
|
||||
metadata = extra_params.get('__metadata__', {})
|
||||
custom_headers = get_custom_headers(connection_headers, user, metadata)
|
||||
headers.update(custom_headers)
|
||||
|
||||
# Add user info headers if enabled
|
||||
if ENABLE_FORWARD_USER_INFO_HEADERS and user:
|
||||
|
||||
@@ -378,6 +378,7 @@ type RegisterOAuthClientForm = {
|
||||
client_id: string;
|
||||
client_name?: string;
|
||||
client_secret?: string;
|
||||
oauth_server_url?: string;
|
||||
};
|
||||
|
||||
export const registerOAuthClient = async (
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
|
||||
let oauthClientId = '';
|
||||
let oauthClientSecret = '';
|
||||
let oauthServerUrl = '';
|
||||
|
||||
let enable = true;
|
||||
let loading = false;
|
||||
@@ -86,10 +87,10 @@
|
||||
// client_id is the tool server ID (used as the internal lookup key for both flows).
|
||||
// For static, client_secret signals the backend to use the static credential path.
|
||||
// The actual OAuth client_id/secret come from the connection info at save time.
|
||||
const formData: { url: string; client_id: string; client_secret?: string } = {
|
||||
const formData: { url: string; client_id: string; client_secret?: string; oauth_server_url?: string } = {
|
||||
url: url,
|
||||
client_id: id,
|
||||
...(auth_type === 'oauth_2.1_static' ? { client_secret: oauthClientSecret } : {})
|
||||
...(auth_type === 'oauth_2.1_static' ? { client_secret: oauthClientSecret, oauth_server_url: oauthServerUrl } : {})
|
||||
};
|
||||
|
||||
const res = await registerOAuthClient(localStorage.token, formData, 'mcp').catch((err) => {
|
||||
@@ -336,7 +337,7 @@
|
||||
description: description,
|
||||
...(oauthClientInfo ? { oauth_client_info: oauthClientInfo } : {}),
|
||||
...(auth_type === 'oauth_2.1_static'
|
||||
? { oauth_client_id: oauthClientId, oauth_client_secret: oauthClientSecret }
|
||||
? { oauth_client_id: oauthClientId, oauth_client_secret: oauthClientSecret, oauth_server_url: oauthServerUrl }
|
||||
: {})
|
||||
}
|
||||
};
|
||||
@@ -364,6 +365,7 @@
|
||||
oauthClientInfo = null;
|
||||
oauthClientId = '';
|
||||
oauthClientSecret = '';
|
||||
oauthServerUrl = '';
|
||||
|
||||
enable = true;
|
||||
functionNameFilterList = '';
|
||||
@@ -390,6 +392,7 @@
|
||||
oauthClientInfo = connection.info?.oauth_client_info ?? null;
|
||||
oauthClientId = connection.info?.oauth_client_id ?? '';
|
||||
oauthClientSecret = connection.info?.oauth_client_secret ?? '';
|
||||
oauthServerUrl = connection.info?.oauth_server_url ?? '';
|
||||
|
||||
enable = connection.config?.enable ?? true;
|
||||
functionNameFilterList = connection.config?.function_name_filter_list ?? '';
|
||||
@@ -730,6 +733,15 @@
|
||||
placeholder={$i18n.t('Client Secret')}
|
||||
required={false}
|
||||
/>
|
||||
<div class="flex flex-1 items-center">
|
||||
<input
|
||||
class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
|
||||
type="text"
|
||||
bind:value={oauthServerUrl}
|
||||
placeholder={$i18n.t('OAuth Server URL')}
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user