This commit is contained in:
Timothy Jaeryang Baek
2026-06-17 02:52:35 +02:00
parent e8d55c0a8b
commit 5cdcdbaeec
53 changed files with 7829 additions and 7954 deletions
+140 -89
View File
@@ -1,18 +1,17 @@
import base64
import copy
import fnmatch
import hashlib
import json
import logging
import mimetypes
import re
import secrets
import sys
import time
import urllib
import uuid
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from types import SimpleNamespace
from typing import Literal, Optional
import aiohttp
@@ -62,7 +61,6 @@ from open_webui.config import (
OAUTH_UPDATE_PICTURE_ON_LOGIN,
OAUTH_USERNAME_CLAIM,
WEBHOOK_URL,
AppConfig,
)
from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES
from open_webui.env import (
@@ -78,6 +76,7 @@ from open_webui.env import (
WEBUI_NAME,
)
from open_webui.models.auths import Auths
from open_webui.models.config import Config
from open_webui.models.groups import GroupForm, GroupModel, Groups, GroupUpdateForm
from open_webui.models.oauth_sessions import OAuthSessions
from open_webui.models.users import Users
@@ -111,31 +110,73 @@ from open_webui.env import GLOBAL_LOG_LEVEL
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
log = logging.getLogger(__name__)
auth_manager_config = AppConfig()
auth_manager_config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
auth_manager_config.ENABLE_OAUTH_SIGNUP = ENABLE_OAUTH_SIGNUP
auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE
auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL = OAUTH_MERGE_ACCOUNTS_BY_EMAIL
auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT
auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT = ENABLE_OAUTH_GROUP_MANAGEMENT
auth_manager_config.ENABLE_OAUTH_GROUP_CREATION = ENABLE_OAUTH_GROUP_CREATION
auth_manager_config.OAUTH_GROUP_DEFAULT_SHARE = OAUTH_GROUP_DEFAULT_SHARE
auth_manager_config.OAUTH_BLOCKED_GROUPS = OAUTH_BLOCKED_GROUPS
auth_manager_config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM
auth_manager_config.OAUTH_SUB_CLAIM = OAUTH_SUB_CLAIM
auth_manager_config.OAUTH_GROUPS_CLAIM = OAUTH_GROUPS_CLAIM
auth_manager_config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
auth_manager_config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM
auth_manager_config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM
auth_manager_config.OAUTH_ALLOWED_ROLES = OAUTH_ALLOWED_ROLES
auth_manager_config.OAUTH_ADMIN_ROLES = OAUTH_ADMIN_ROLES
auth_manager_config.OAUTH_ALLOWED_DOMAINS = OAUTH_ALLOWED_DOMAINS
auth_manager_config.WEBHOOK_URL = WEBHOOK_URL
auth_manager_config.JWT_EXPIRES_IN = JWT_EXPIRES_IN
auth_manager_config.OAUTH_UPDATE_PICTURE_ON_LOGIN = OAUTH_UPDATE_PICTURE_ON_LOGIN
auth_manager_config.OAUTH_UPDATE_NAME_ON_LOGIN = OAUTH_UPDATE_NAME_ON_LOGIN
auth_manager_config.OAUTH_UPDATE_EMAIL_ON_LOGIN = OAUTH_UPDATE_EMAIL_ON_LOGIN
auth_manager_config.OAUTH_AUDIENCE = OAUTH_AUDIENCE
OAUTH_RUNTIME_CONFIG = {
'DEFAULT_USER_ROLE': ('ui.default_user_role', DEFAULT_USER_ROLE),
'ENABLE_OAUTH_SIGNUP': ('oauth.enable_signup', ENABLE_OAUTH_SIGNUP),
'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE': (
'oauth.refresh_token.include_scope',
OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE,
),
'OAUTH_MERGE_ACCOUNTS_BY_EMAIL': (
'oauth.merge_accounts_by_email',
OAUTH_MERGE_ACCOUNTS_BY_EMAIL,
),
'ENABLE_OAUTH_ROLE_MANAGEMENT': (
'oauth.enable_role_mapping',
ENABLE_OAUTH_ROLE_MANAGEMENT,
),
'ENABLE_OAUTH_GROUP_MANAGEMENT': (
'oauth.enable_group_mapping',
ENABLE_OAUTH_GROUP_MANAGEMENT,
),
'ENABLE_OAUTH_GROUP_CREATION': (
'oauth.enable_group_creation',
ENABLE_OAUTH_GROUP_CREATION,
),
'OAUTH_GROUP_DEFAULT_SHARE': (
'oauth.group_default_share',
OAUTH_GROUP_DEFAULT_SHARE,
),
'OAUTH_BLOCKED_GROUPS': ('oauth.blocked_groups', OAUTH_BLOCKED_GROUPS),
'OAUTH_ROLES_CLAIM': ('oauth.roles_claim', OAUTH_ROLES_CLAIM),
'OAUTH_SUB_CLAIM': ('oauth.sub_claim', OAUTH_SUB_CLAIM),
'OAUTH_GROUPS_CLAIM': ('oauth.group_claim', OAUTH_GROUPS_CLAIM),
'OAUTH_EMAIL_CLAIM': ('oauth.email_claim', OAUTH_EMAIL_CLAIM),
'OAUTH_PICTURE_CLAIM': ('oauth.picture_claim', OAUTH_PICTURE_CLAIM),
'OAUTH_USERNAME_CLAIM': ('oauth.username_claim', OAUTH_USERNAME_CLAIM),
'OAUTH_ALLOWED_ROLES': ('oauth.allowed_roles', OAUTH_ALLOWED_ROLES),
'OAUTH_ADMIN_ROLES': ('oauth.admin_roles', OAUTH_ADMIN_ROLES),
'OAUTH_ALLOWED_DOMAINS': ('oauth.allowed_domains', OAUTH_ALLOWED_DOMAINS),
'WEBHOOK_URL': ('webhook_url', WEBHOOK_URL),
'JWT_EXPIRES_IN': ('auth.jwt_expiry', JWT_EXPIRES_IN),
'OAUTH_UPDATE_PICTURE_ON_LOGIN': (
'oauth.update_picture_on_login',
OAUTH_UPDATE_PICTURE_ON_LOGIN,
),
'OAUTH_UPDATE_NAME_ON_LOGIN': (
'oauth.update_name_on_login',
OAUTH_UPDATE_NAME_ON_LOGIN,
),
'OAUTH_UPDATE_EMAIL_ON_LOGIN': (
'oauth.update_email_on_login',
OAUTH_UPDATE_EMAIL_ON_LOGIN,
),
'OAUTH_AUDIENCE': ('oauth.audience', OAUTH_AUDIENCE),
}
def _default_value(value):
return getattr(value, 'value', value)
async def get_oauth_runtime_config() -> SimpleNamespace:
keys = [key for key, _default in OAUTH_RUNTIME_CONFIG.values()]
stored = await Config.get_many(*keys)
values = {
name: stored.get(key, _default_value(default))
for name, (key, default) in OAUTH_RUNTIME_CONFIG.items()
}
return SimpleNamespace(**values)
# Conservative default when the provider omits both expires_in and expires_at.
@@ -423,7 +464,8 @@ async def get_oauth_client_info_with_dynamic_client_registration(
oauth_server_metadata = None
oauth_server_metadata_url = None
redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/')
webui_url = await Config.get('webui.url')
redirect_base_url = (str(webui_url or request.base_url)).rstrip('/')
oauth_client_metadata = OAuthClientMetadata(
client_name='Open WebUI',
@@ -549,7 +591,8 @@ async def get_oauth_client_info_with_static_credentials(
oauth_server_metadata = None
oauth_server_metadata_url = None
redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/')
webui_url = await Config.get('webui.url')
redirect_base_url = (str(webui_url or request.base_url)).rstrip('/')
redirect_uri = f'{redirect_base_url}/oauth/clients/{client_id}/callback'
# Discover server metadata (authorization endpoint, token endpoint, scopes, etc.)
@@ -636,7 +679,7 @@ class OAuthClientManager:
'client_secret': oauth_client_info.client_secret,
'client_kwargs': {
'follow_redirects': True,
**({'timeout': int(OAUTH_CLIENT_TIMEOUT.value)} if OAUTH_CLIENT_TIMEOUT.value else {}),
**({'timeout': int(OAUTH_CLIENT_TIMEOUT)} if OAUTH_CLIENT_TIMEOUT else {}),
**({'scope': oauth_client_info.scope} if oauth_client_info.scope else {}),
**(
{'token_endpoint_auth_method': oauth_client_info.token_endpoint_auth_method}
@@ -668,7 +711,7 @@ class OAuthClientManager:
}
return self.clients[client_id]
def ensure_client_from_config(self, client_id):
async def ensure_client_from_config(self, client_id):
"""
Lazy-load an OAuth client from the current TOOL_SERVER_CONNECTIONS
config if it hasn't been registered on this node yet.
@@ -677,7 +720,7 @@ class OAuthClientManager:
return self.clients[client_id]['client']
try:
connections = getattr(self.app.state.config, 'TOOL_SERVER_CONNECTIONS', [])
connections = await Config.get('tool_server.connections', [])
except Exception:
connections = []
@@ -783,22 +826,22 @@ class OAuthClientManager:
return True
def get_client(self, client_id):
async def get_client(self, client_id):
if client_id not in self.clients:
self.ensure_client_from_config(client_id)
await self.ensure_client_from_config(client_id)
client = self.clients.get(client_id)
return client['client'] if client else None
def get_client_info(self, client_id):
async def get_client_info(self, client_id):
if client_id not in self.clients:
self.ensure_client_from_config(client_id)
await self.ensure_client_from_config(client_id)
client = self.clients.get(client_id)
return client['client_info'] if client else None
def get_server_metadata_url(self, client_id):
client = self.get_client(client_id)
async def get_server_metadata_url(self, client_id):
client = await self.get_client(client_id)
if not client:
return None
@@ -881,6 +924,7 @@ class OAuthClientManager:
Returns:
dict: New token data, or None if refresh failed
"""
auth_config = await get_oauth_runtime_config()
client_id = session.provider
token_data = session.token
@@ -889,14 +933,14 @@ class OAuthClientManager:
return None
try:
client = self.get_client(client_id)
client = await self.get_client(client_id)
if not client:
log.error(f'No OAuth client found for provider {client_id}')
return None
token_endpoint = None
async with aiohttp.ClientSession(trust_env=True) as session_http:
async with session_http.get(self.get_server_metadata_url(client_id)) as r:
async with session_http.get(await self.get_server_metadata_url(client_id)) as r:
if r.status == 200:
openid_data = await r.json()
token_endpoint = openid_data.get('token_endpoint')
@@ -913,7 +957,7 @@ class OAuthClientManager:
'client_id': client.client_id,
}
# RFC 8707: include resource indicator so refreshed tokens retain correct audience
client_info = self.get_client_info(client_id)
client_info = await self.get_client_info(client_id)
if client_info and client_info.resource:
refresh_data['resource'] = client_info.resource
@@ -924,7 +968,7 @@ class OAuthClientManager:
if (
hasattr(client, 'client_kwargs')
and client.client_kwargs.get('scope')
and getattr(self.app.state.config, 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', False)
and auth_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE
):
refresh_data['scope'] = client.client_kwargs['scope']
@@ -957,13 +1001,13 @@ class OAuthClientManager:
return None
async def handle_authorize(self, request, client_id: str) -> RedirectResponse:
client = self.get_client(client_id) or self.ensure_client_from_config(client_id)
client = await self.get_client(client_id)
if client is None:
raise HTTPException(404)
client_info = self.get_client_info(client_id)
client_info = await self.get_client_info(client_id)
if client_info is None:
# ensure_client_from_config registers client_info too
client_info = self.get_client_info(client_id)
# get_client registers client_info too
client_info = await self.get_client_info(client_id)
if client_info is None:
raise HTTPException(404)
@@ -976,13 +1020,13 @@ class OAuthClientManager:
return await client.authorize_redirect(request, redirect_uri_str, **kwargs)
async def handle_callback(self, request, client_id: str, user_id: str, response):
client = self.get_client(client_id) or self.ensure_client_from_config(client_id)
client = await self.get_client(client_id)
if client is None:
raise HTTPException(404)
error_message = None
try:
client_info = self.get_client_info(client_id)
client_info = await self.get_client_info(client_id)
# Note: Do NOT pass client_id/client_secret explicitly here.
# The Authlib client already has these configured during add_client().
@@ -1035,7 +1079,8 @@ class OAuthClientManager:
exc_info=True,
)
redirect_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/')
webui_url = await Config.get('webui.url')
redirect_url = (str(webui_url or request.base_url)).rstrip('/')
if error_message:
log.debug(error_message)
@@ -1202,7 +1247,7 @@ class OAuthManager:
if (
hasattr(client, 'client_kwargs')
and client.client_kwargs.get('scope')
and auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE
and auth_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE
):
refresh_data['scope'] = client.client_kwargs['scope']
@@ -1235,6 +1280,7 @@ class OAuthManager:
return None
async def get_user_role(self, user, user_data):
auth_config = await get_oauth_runtime_config()
user_count = await Users.get_num_users()
if user and user_count == 1:
# If the user is the only user, assign the role "admin" - actually repairs role for single user on login
@@ -1246,16 +1292,16 @@ class OAuthManager:
# default role here (not 'admin') — admin promotion happens
# race-safely *after* insert via get_num_users() == 1.
log.debug('First user bootstrap: using default role (admin promotion deferred to post-insert)')
return auth_manager_config.DEFAULT_USER_ROLE
return auth_config.DEFAULT_USER_ROLE
if auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT:
if auth_config.ENABLE_OAUTH_ROLE_MANAGEMENT:
log.debug('Running OAUTH Role management')
oauth_claim = auth_manager_config.OAUTH_ROLES_CLAIM
oauth_allowed_roles = auth_manager_config.OAUTH_ALLOWED_ROLES
oauth_admin_roles = auth_manager_config.OAUTH_ADMIN_ROLES
oauth_claim = auth_config.OAUTH_ROLES_CLAIM
oauth_allowed_roles = auth_config.OAUTH_ALLOWED_ROLES
oauth_admin_roles = auth_config.OAUTH_ADMIN_ROLES
oauth_roles = []
# Default/fallback role if no matching roles are found
role = auth_manager_config.DEFAULT_USER_ROLE
role = auth_config.DEFAULT_USER_ROLE
# Next block extracts the roles from the user data, accepting nested claims of any depth
if oauth_claim and oauth_allowed_roles and oauth_admin_roles:
@@ -1313,7 +1359,7 @@ class OAuthManager:
else:
if not user:
# If role management is disabled, use the default role for new users
role = auth_manager_config.DEFAULT_USER_ROLE
role = auth_config.DEFAULT_USER_ROLE
else:
# If role management is disabled, use the existing role for existing users
role = user.role
@@ -1321,11 +1367,12 @@ class OAuthManager:
return role
async def update_user_groups(self, user, user_data, default_permissions, db=None):
auth_config = await get_oauth_runtime_config()
log.debug('Running OAUTH Group management')
oauth_claim = auth_manager_config.OAUTH_GROUPS_CLAIM
oauth_claim = auth_config.OAUTH_GROUPS_CLAIM
try:
blocked_groups = json.loads(auth_manager_config.OAUTH_BLOCKED_GROUPS)
blocked_groups = json.loads(auth_config.OAUTH_BLOCKED_GROUPS)
except Exception as e:
log.exception(f'Error loading OAUTH_BLOCKED_GROUPS: {e}')
blocked_groups = []
@@ -1353,7 +1400,7 @@ class OAuthManager:
all_available_groups: list[GroupModel] = await Groups.get_all_groups(db=db)
# Create groups if they don't exist and creation is enabled
if auth_manager_config.ENABLE_OAUTH_GROUP_CREATION:
if auth_config.ENABLE_OAUTH_GROUP_CREATION:
log.debug('Checking for missing groups to create...')
all_group_names = {g.name for g in all_available_groups}
groups_created = False
@@ -1370,7 +1417,7 @@ class OAuthManager:
name=group_name,
description=f"Group '{group_name}' created automatically via OAuth.",
permissions=default_permissions, # Use default permissions from function args
data={'config': {'share': auth_manager_config.OAUTH_GROUP_DEFAULT_SHARE}},
data={'config': {'share': auth_config.OAUTH_GROUP_DEFAULT_SHARE}},
)
# Use determined creator ID (admin or fallback to current user)
created_group = await Groups.insert_new_group(creator_id, new_group_form, db=db)
@@ -1496,6 +1543,7 @@ class OAuthManager:
return '/user.png'
async def handle_login(self, request, provider):
auth_config = await get_oauth_runtime_config()
if provider not in OAUTH_PROVIDERS:
raise HTTPException(404)
# If the provider has a custom redirect URL, use that, otherwise automatically generate one
@@ -1507,14 +1555,15 @@ class OAuthManager:
)
kwargs = {}
if auth_manager_config.OAUTH_AUDIENCE:
kwargs['audience'] = auth_manager_config.OAUTH_AUDIENCE
if auth_config.OAUTH_AUDIENCE:
kwargs['audience'] = auth_config.OAUTH_AUDIENCE
if OAUTH_AUTHORIZE_PARAMS:
kwargs.update(OAUTH_AUTHORIZE_PARAMS)
return await client.authorize_redirect(request, redirect_uri, **kwargs)
async def handle_callback(self, request, provider, response, db=None):
auth_config = await get_oauth_runtime_config()
if provider not in OAUTH_PROVIDERS:
raise HTTPException(404)
@@ -1568,8 +1617,8 @@ class OAuthManager:
id_token_claims = dict(user_data) if user_data else {}
if (
(not user_data)
or (auth_manager_config.OAUTH_EMAIL_CLAIM not in user_data)
or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data)
or (auth_config.OAUTH_EMAIL_CLAIM not in user_data)
or (auth_config.OAUTH_USERNAME_CLAIM not in user_data)
):
user_data: UserInfo = await client.userinfo(token=token)
# Merge back ID token claims that the userinfo endpoint doesn't
@@ -1585,8 +1634,8 @@ class OAuthManager:
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
# Extract the "sub" claim, using custom claim if configured
if auth_manager_config.OAUTH_SUB_CLAIM:
sub = user_data.get(auth_manager_config.OAUTH_SUB_CLAIM)
if auth_config.OAUTH_SUB_CLAIM:
sub = user_data.get(auth_config.OAUTH_SUB_CLAIM)
else:
# Fallback to the default sub claim if not configured
sub = user_data.get(OAUTH_PROVIDERS[provider].get('sub_claim', 'sub'))
@@ -1600,7 +1649,7 @@ class OAuthManager:
}
# Email extraction
email_claim = auth_manager_config.OAUTH_EMAIL_CLAIM
email_claim = auth_config.OAUTH_EMAIL_CLAIM
email = user_data.get(email_claim, '')
# We currently mandate that email addresses are provided
if not email:
@@ -1642,8 +1691,8 @@ class OAuthManager:
email = email.lower()
# If allowed domains are configured, check if the email domain is in the list
if (
'*' not in auth_manager_config.OAUTH_ALLOWED_DOMAINS
and email.split('@')[-1] not in auth_manager_config.OAUTH_ALLOWED_DOMAINS
'*' not in auth_config.OAUTH_ALLOWED_DOMAINS
and email.split('@')[-1] not in auth_config.OAUTH_ALLOWED_DOMAINS
):
log.warning(f'OAuth callback failed, e-mail domain is not in the list of allowed domains: {user_data}')
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
@@ -1652,7 +1701,7 @@ class OAuthManager:
user = await Users.get_user_by_oauth_sub(provider, sub, db=db)
if not user:
# If the user does not exist, check if merging is enabled
if auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL:
if auth_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL:
# Check if the user exists by email
user = await Users.get_user_by_email(email, db=db)
if user:
@@ -1667,8 +1716,8 @@ class OAuthManager:
# to avoid problems with the ENABLE_OAUTH_GROUP_MANAGEMENT check below
user.role = determined_role
if auth_manager_config.OAUTH_UPDATE_NAME_ON_LOGIN:
username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM
if auth_config.OAUTH_UPDATE_NAME_ON_LOGIN:
username_claim = auth_config.OAUTH_USERNAME_CLAIM
if username_claim:
new_name = user_data.get(username_claim)
if new_name and new_name != user.name:
@@ -1676,8 +1725,8 @@ class OAuthManager:
user.name = new_name
log.debug(f'Updated name for user {user.email}')
if auth_manager_config.OAUTH_UPDATE_EMAIL_ON_LOGIN:
email_claim = auth_manager_config.OAUTH_EMAIL_CLAIM
if auth_config.OAUTH_UPDATE_EMAIL_ON_LOGIN:
email_claim = auth_config.OAUTH_EMAIL_CLAIM
if email_claim:
new_email = user_data.get(email_claim)
if new_email and new_email.lower() != user.email.lower():
@@ -1692,8 +1741,8 @@ class OAuthManager:
log.debug(f'Updated email for user {user.id}')
# Update profile picture if enabled and different from current
if auth_manager_config.OAUTH_UPDATE_PICTURE_ON_LOGIN:
picture_claim = auth_manager_config.OAUTH_PICTURE_CLAIM
if auth_config.OAUTH_UPDATE_PICTURE_ON_LOGIN:
picture_claim = auth_config.OAUTH_PICTURE_CLAIM
if picture_claim:
new_picture_url = user_data.get(
picture_claim,
@@ -1707,13 +1756,13 @@ class OAuthManager:
log.debug(f'Updated profile picture for user {user.email}')
else:
# If the user does not exist, check if signups are enabled
if auth_manager_config.ENABLE_OAUTH_SIGNUP:
if auth_config.ENABLE_OAUTH_SIGNUP:
# Check if an existing user with the same email already exists
existing_user = await Users.get_user_by_email(email, db=db)
if existing_user:
raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN)
picture_claim = auth_manager_config.OAUTH_PICTURE_CLAIM
picture_claim = auth_config.OAUTH_PICTURE_CLAIM
if picture_claim:
picture_url = user_data.get(
picture_claim,
@@ -1722,7 +1771,7 @@ class OAuthManager:
picture_url = await self._process_picture_url(picture_url, token.get('access_token'))
else:
picture_url = '/user.png'
username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM
username_claim = auth_config.OAUTH_USERNAME_CLAIM
name = user_data.get(username_claim)
if not name:
@@ -1749,10 +1798,10 @@ class OAuthManager:
await Users.update_user_role_by_id(user.id, 'admin', db=db)
user = await Users.get_user_by_id(user.id, db=db)
if auth_manager_config.WEBHOOK_URL:
if auth_config.WEBHOOK_URL:
await post_webhook(
WEBUI_NAME,
auth_manager_config.WEBHOOK_URL,
auth_config.WEBHOOK_URL,
WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
{
'action': 'signup',
@@ -1761,7 +1810,8 @@ class OAuthManager:
},
)
await apply_default_group_assignment(request.app.state.config.DEFAULT_GROUP_ID, user.id, db=db)
default_group_id = await Config.get('ui.default_group_id')
await apply_default_group_assignment(default_group_id, user.id, db=db)
else:
raise HTTPException(
@@ -1771,13 +1821,13 @@ class OAuthManager:
jwt_token = create_token(
data={'id': user.id},
expires_delta=parse_duration(auth_manager_config.JWT_EXPIRES_IN),
expires_delta=parse_duration(auth_config.JWT_EXPIRES_IN),
)
if auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT:
if auth_config.ENABLE_OAUTH_GROUP_MANAGEMENT:
await self.update_user_groups(
user=user,
user_data=user_data,
default_permissions=request.app.state.config.USER_PERMISSIONS,
default_permissions=await Config.get('user.permissions'),
db=db,
)
@@ -1789,7 +1839,8 @@ class OAuthManager:
else ERROR_MESSAGES.DEFAULT('Error during OAuth process')
)
redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/')
webui_url = await Config.get('webui.url')
redirect_base_url = (str(webui_url or request.base_url)).rstrip('/')
redirect_url = f'{redirect_base_url}/auth'
if error_message:
@@ -1799,7 +1850,7 @@ class OAuthManager:
response = RedirectResponse(url=redirect_url, headers=response.headers)
# Compute cookie expiry from JWT lifetime
expires_delta = parse_duration(auth_manager_config.JWT_EXPIRES_IN)
expires_delta = parse_duration(auth_config.JWT_EXPIRES_IN)
cookie_max_age = int(expires_delta.total_seconds()) if expires_delta else None
# Set the cookie token