refac
This commit is contained in:
1 parent
b7de04da14
commit
c2107e5bb3
4 files changed
+81
-7
No files matched your search
@@ -2649,7 +2649,7 @@ async def oauth_client_authorize(
|
|||||||
detail='OAuth client registration is still invalid after re-registration',
|
detail='OAuth client registration is still invalid after re-registration',
|
||||||
)
|
)
|
||||||
|
|
||||||
return await oauth_client_manager.handle_authorize(request, client_id=client_id)
|
return await oauth_client_manager.handle_authorize(request, client_id=client_id, user_id=user.id)
|
||||||
|
|
||||||
|
|
||||||
@app.get('/oauth/clients/{client_id}/callback')
|
@app.get('/oauth/clients/{client_id}/callback')
|
||||||
@@ -2657,12 +2657,10 @@ async def oauth_client_callback(
|
|||||||
client_id: str,
|
client_id: str,
|
||||||
request: Request,
|
request: Request,
|
||||||
response: Response,
|
response: Response,
|
||||||
user=Depends(get_verified_user),
|
|
||||||
):
|
):
|
||||||
return await oauth_client_manager.handle_callback(
|
return await oauth_client_manager.handle_callback(
|
||||||
request,
|
request,
|
||||||
client_id=client_id,
|
client_id=client_id,
|
||||||
user_id=user.id if user else None,
|
|
||||||
response=response,
|
response=response,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -966,6 +966,11 @@ async def signout(request: Request, response: Response, db: AsyncSession = Depen
|
|||||||
)
|
)
|
||||||
|
|
||||||
response.delete_cookie('token')
|
response.delete_cookie('token')
|
||||||
|
try:
|
||||||
|
request.session.clear()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
response.delete_cookie('owui-session')
|
||||||
response.delete_cookie('oui-session')
|
response.delete_cookie('oui-session')
|
||||||
response.delete_cookie('oauth_id_token')
|
response.delete_cookie('oauth_id_token')
|
||||||
|
|
||||||
|
|||||||
@@ -519,6 +519,39 @@ async def get_verified_user_by_token(token: str, redis=None):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
async def get_verified_user_by_id(user_id: str | None):
|
||||||
|
if not user_id:
|
||||||
|
return None
|
||||||
|
|
||||||
|
user = await Users.get_user_by_id(user_id)
|
||||||
|
if user is None or user.role not in VERIFIED_USER_ROLES:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
async def get_optional_verified_user_from_request(request: Request):
|
||||||
|
token = None
|
||||||
|
auth_token = get_http_authorization_cred(request.headers.get('Authorization'))
|
||||||
|
if auth_token:
|
||||||
|
token = auth_token.credentials
|
||||||
|
if token is None:
|
||||||
|
token = request.cookies.get('token')
|
||||||
|
if token is None and getattr(request.state, 'token', None):
|
||||||
|
token = request.state.token.credentials
|
||||||
|
if not token:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if token.startswith('sk-'):
|
||||||
|
user = await get_current_user_by_api_key(request, token)
|
||||||
|
return user if user.role in VERIFIED_USER_ROLES else None
|
||||||
|
|
||||||
|
return await get_verified_user_by_token(token, getattr(request.app.state, 'redis', None))
|
||||||
|
except HTTPException:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_admin_user(user=Depends(get_current_user)):
|
def get_admin_user(user=Depends(get_current_user)):
|
||||||
if user.role != 'admin':
|
if user.role != 'admin':
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|||||||
@@ -84,7 +84,12 @@ from open_webui.models.groups import GroupForm, GroupModel, Groups, GroupUpdateF
|
|||||||
from open_webui.models.oauth_sessions import OAuthSessions
|
from open_webui.models.oauth_sessions import OAuthSessions
|
||||||
from open_webui.models.users import Users
|
from open_webui.models.users import Users
|
||||||
from open_webui.retrieval.web.utils import get_ssrf_safe_session, validate_url
|
from open_webui.retrieval.web.utils import get_ssrf_safe_session, validate_url
|
||||||
from open_webui.utils.auth import create_token, get_password_hash
|
from open_webui.utils.auth import (
|
||||||
|
create_token,
|
||||||
|
get_password_hash,
|
||||||
|
get_optional_verified_user_from_request,
|
||||||
|
get_verified_user_by_id,
|
||||||
|
)
|
||||||
from open_webui.utils.groups import apply_default_group_assignment
|
from open_webui.utils.groups import apply_default_group_assignment
|
||||||
from open_webui.utils.misc import parse_duration
|
from open_webui.utils.misc import parse_duration
|
||||||
from open_webui.utils.validate import validate_profile_image_url
|
from open_webui.utils.validate import validate_profile_image_url
|
||||||
@@ -1167,7 +1172,7 @@ class OAuthClientManager:
|
|||||||
log.error(f'Exception during token refresh for client_id {client_id}: {e}')
|
log.error(f'Exception during token refresh for client_id {client_id}: {e}')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def handle_authorize(self, request, client_id: str) -> RedirectResponse:
|
async def handle_authorize(self, request, client_id: str, user_id: str) -> RedirectResponse:
|
||||||
client = await self.get_client(client_id)
|
client = await self.get_client(client_id)
|
||||||
if client is None:
|
if client is None:
|
||||||
raise HTTPException(404)
|
raise HTTPException(404)
|
||||||
@@ -1183,7 +1188,15 @@ class OAuthClientManager:
|
|||||||
# Pass explicit scope/resource parameters for providers that require them.
|
# Pass explicit scope/resource parameters for providers that require them.
|
||||||
kwargs = build_oauth_request_params(client_info)
|
kwargs = build_oauth_request_params(client_info)
|
||||||
try:
|
try:
|
||||||
return await client.authorize_redirect(request, redirect_uri_str, **kwargs)
|
auth_data = await client.create_authorization_url(redirect_uri_str, **kwargs)
|
||||||
|
if not auth_data.get('state'):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail='OAuth authorization state was not generated',
|
||||||
|
)
|
||||||
|
auth_data['user_id'] = user_id
|
||||||
|
await client.save_authorize_data(request, redirect_uri=redirect_uri_str, **auth_data)
|
||||||
|
return RedirectResponse(auth_data['url'], status_code=302)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
# authlib raises RuntimeError('Missing "authorize_url" value') when the
|
# authlib raises RuntimeError('Missing "authorize_url" value') when the
|
||||||
# authorization endpoint could not be resolved from server metadata.
|
# authorization endpoint could not be resolved from server metadata.
|
||||||
@@ -1199,14 +1212,36 @@ class OAuthClientManager:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def handle_callback(self, request, client_id: str, user_id: str, response):
|
async def handle_callback(self, request, client_id: str, response):
|
||||||
client = await self.get_client(client_id)
|
client = await self.get_client(client_id)
|
||||||
if client is None:
|
if client is None:
|
||||||
raise HTTPException(404)
|
raise HTTPException(404)
|
||||||
|
|
||||||
error_message = None
|
error_message = None
|
||||||
|
state = request.query_params.get('state')
|
||||||
|
user_id = None
|
||||||
try:
|
try:
|
||||||
client_info = await self.get_client_info(client_id)
|
client_info = await self.get_client_info(client_id)
|
||||||
|
state_data = await client.framework.get_state_data(request.session, state) if state else None
|
||||||
|
user_id = state_data.get('user_id') if state_data else None
|
||||||
|
if not user_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail='OAuth callback state is invalid or expired',
|
||||||
|
)
|
||||||
|
|
||||||
|
if not await get_verified_user_by_id(user_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail='OAuth callback user is not authorized',
|
||||||
|
)
|
||||||
|
|
||||||
|
request_user = await get_optional_verified_user_from_request(request)
|
||||||
|
if request_user and request_user.id != user_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail='OAuth callback user does not match authenticated session',
|
||||||
|
)
|
||||||
|
|
||||||
# Note: Do NOT pass client_id/client_secret explicitly here.
|
# Note: Do NOT pass client_id/client_secret explicitly here.
|
||||||
# The Authlib client already has these configured during add_client().
|
# The Authlib client already has these configured during add_client().
|
||||||
@@ -1257,6 +1292,9 @@ class OAuthClientManager:
|
|||||||
error_message,
|
error_message,
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
|
finally:
|
||||||
|
if state and client is not None:
|
||||||
|
await client.framework.clear_state_data(request.session, state)
|
||||||
|
|
||||||
webui_url = await Config.get('webui.url')
|
webui_url = await Config.get('webui.url')
|
||||||
redirect_url = (str(webui_url or request.base_url)).rstrip('/')
|
redirect_url = (str(webui_url or request.base_url)).rstrip('/')
|
||||||
|
|||||||
Reference in new issue
Block a user