mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-27 01:40:33 -04:00
refac
This commit is contained in:
@@ -1752,6 +1752,7 @@ async def token_exchange(
|
||||
user=user,
|
||||
user_data=user_data,
|
||||
provider=provider,
|
||||
access_token=form_data.token,
|
||||
db=db,
|
||||
)
|
||||
if await Config.get('oauth.enable_group_mapping'):
|
||||
|
||||
@@ -188,6 +188,16 @@ def _default_value(value):
|
||||
return getattr(value, 'value', value)
|
||||
|
||||
|
||||
def _get_roles_claim(claims: dict, claim: str) -> list | str | int | None:
|
||||
"""Read nested or flat claims, preserving explicit empty values and zero."""
|
||||
value = claims
|
||||
for key in claim.split('.'):
|
||||
value = value.get(key) if isinstance(value, dict) else None
|
||||
if not isinstance(value, (list, str, int)):
|
||||
value = claims.get(claim)
|
||||
return value if isinstance(value, (list, str, int)) else None
|
||||
|
||||
|
||||
async def get_oauth_runtime_config() -> SimpleNamespace:
|
||||
keys = [key for key, _default in OAUTH_RUNTIME_CONFIG.values()]
|
||||
stored = await Config.get_many(*keys)
|
||||
@@ -1505,7 +1515,7 @@ class OAuthManager:
|
||||
log.error(f'Exception during token refresh for provider {provider}: {e}')
|
||||
return None
|
||||
|
||||
async def get_user_role(self, user, user_data):
|
||||
async def get_user_role(self, user, user_data, *, access_token: str | None = None):
|
||||
auth_config = await get_oauth_runtime_config()
|
||||
user_count = await Users.get_num_users()
|
||||
if user and user_count == 1:
|
||||
@@ -1529,18 +1539,15 @@ class OAuthManager:
|
||||
# Keep existing users at their current role unless the provider sent roles.
|
||||
role = user.role if user else 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:
|
||||
claim_data = user_data
|
||||
nested_claims = oauth_claim.split('.')
|
||||
for nested_claim in nested_claims:
|
||||
claim_data = claim_data.get(nested_claim, {})
|
||||
|
||||
# Try flat claim structure as alternative
|
||||
if not claim_data:
|
||||
claim_data = user_data.get(oauth_claim, {})
|
||||
|
||||
oauth_roles = []
|
||||
if oauth_claim:
|
||||
claim_data = _get_roles_claim(user_data, oauth_claim)
|
||||
if claim_data is None and access_token is not None:
|
||||
# The exchange endpoint has already validated this token with the provider's userinfo endpoint.
|
||||
try:
|
||||
token_claims = jwt.decode(access_token, options={'verify_signature': False})
|
||||
claim_data = _get_roles_claim(token_claims, oauth_claim)
|
||||
except jwt.PyJWTError as e:
|
||||
log.debug('Token exchange: cannot decode token claims: %s', e)
|
||||
|
||||
if isinstance(claim_data, list):
|
||||
oauth_roles = claim_data
|
||||
@@ -1553,6 +1560,10 @@ class OAuthManager:
|
||||
elif isinstance(claim_data, int):
|
||||
oauth_roles = [str(claim_data)]
|
||||
|
||||
if access_token is not None and not oauth_roles and oauth_allowed_roles and '*' not in oauth_allowed_roles:
|
||||
log.warning('Token exchange denied: no readable roles claim in userinfo or the token')
|
||||
raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED)
|
||||
|
||||
log.debug('Oauth Roles claim: %s', oauth_claim)
|
||||
log.debug('User roles from oauth: %s', oauth_roles)
|
||||
log.debug('Accepted user roles: %s', oauth_allowed_roles)
|
||||
@@ -1599,9 +1610,10 @@ class OAuthManager:
|
||||
user_data,
|
||||
provider,
|
||||
*,
|
||||
access_token: str | None = None,
|
||||
db=None,
|
||||
):
|
||||
determined_role = await self.get_user_role(user, user_data)
|
||||
determined_role = await self.get_user_role(user, user_data, access_token=access_token)
|
||||
if user.role == determined_role:
|
||||
return user
|
||||
|
||||
|
||||
Reference in New Issue
Block a user