diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 86de689458..15f9c0c429 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -1705,4 +1705,17 @@ async def token_exchange( detail='User not found. Please sign in via the web interface first.', ) + role = await oauth_manager.get_user_role(user, user_data, deny_on_missing_roles=True) + if user.role != role: + await Users.update_user_role_by_id(user.id, role, db=db) + user.role = role + await publish_event( + request, + EVENTS.USER_ROLE_UPDATED, + actor=user, + subject_id=user.id, + source='oauth', + data={'role': role, 'provider': provider}, + ) + return await create_session_response(request, user, db, source='oauth') diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index fce053dae8..9ae58de945 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -1498,7 +1498,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, deny_on_missing_roles=False): auth_config = await get_oauth_runtime_config() user_count = await Users.get_num_users() if user and user_count == 1: @@ -1551,6 +1551,14 @@ class OAuthManager: log.debug('Accepted user roles: %s', oauth_allowed_roles) log.debug('Accepted admin roles: %s', oauth_admin_roles) + # No ID token here to backfill claims from, so falling back to DEFAULT_USER_ROLE would demote the user. + if not oauth_roles and deny_on_missing_roles: + log.warning('OAuth role management enabled but no roles resolved for the user; denying token exchange') + raise HTTPException( + status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + # If roles are present in the token, they must match; otherwise deny access if oauth_roles: matched = False