From 6ff1df326c76824f0706671b0974df4035cb453f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 23 Jul 2026 03:05:29 -0400 Subject: [PATCH] refac --- backend/open_webui/utils/asgi_middleware.py | 6 +----- backend/open_webui/utils/auth.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/backend/open_webui/utils/asgi_middleware.py b/backend/open_webui/utils/asgi_middleware.py index 1ed539fefa..89154b6103 100644 --- a/backend/open_webui/utils/asgi_middleware.py +++ b/backend/open_webui/utils/asgi_middleware.py @@ -39,7 +39,6 @@ from fastapi.responses import JSONResponse, RedirectResponse from fastapi.security import HTTPAuthorizationCredentials from open_webui.env import CUSTOM_API_KEY_HEADER from open_webui.internal.db import ScopedSession -from open_webui.models.config import Config from open_webui.utils.auth import get_http_authorization_cred from starlette.datastructures import MutableHeaders from starlette.requests import Request @@ -138,9 +137,7 @@ class AuthTokenMiddleware: the middleware checks that instead and avoids the 401 short-circuit. Routes that depend on `get_verified_user` etc. read this state. - Also exposes `request.state.enable_api_keys` (snapshotted at request - entry from runtime config) and stamps an `X-Process-Time` response - header. + Also stamps an `X-Process-Time` response header. """ def __init__(self, app: ASGIApp, *, fastapi_app) -> None: @@ -166,7 +163,6 @@ class AuthTokenMiddleware: token = HTTPAuthorizationCredentials(scheme='Bearer', credentials=api_key) request.state.token = token - request.state.enable_api_keys = await Config.get('auth.enable_api_keys') async def send_with_timing(message: Message) -> None: if message['type'] == 'http.response.start': diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py index c8ff94bc09..7e5dc24a91 100644 --- a/backend/open_webui/utils/auth.py +++ b/backend/open_webui/utils/auth.py @@ -437,24 +437,24 @@ async def get_current_user_by_api_key(request, api_key: str): detail=ERROR_MESSAGES.INVALID_TOKEN, ) - user_permissions = await Config.get('user.permissions') - enable_endpoint_restrictions = await Config.get('auth.api_key.endpoint_restrictions') - allowed_endpoints = await Config.get('auth.api_key.allowed_endpoints', '') + if not await Config.get('auth.enable_api_keys'): + raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED) - if not request.state.enable_api_keys or ( - user.role != 'admin' - and not await has_permission( + if user.role != 'admin': + user_permissions = await Config.get('user.permissions') + if not await has_permission( user.id, 'features.api_keys', user_permissions, - ) - ): - raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED) + ): + raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED) # Enforce endpoint restrictions — checked here (not in middleware) # so it applies regardless of how the API key was transported # (Authorization header, cookie, x-api-key header, etc.). + enable_endpoint_restrictions = await Config.get('auth.api_key.endpoint_restrictions') if enable_endpoint_restrictions: + allowed_endpoints = await Config.get('auth.api_key.allowed_endpoints', '') allowed_paths = [path.strip() for path in str(allowed_endpoints).split(',') if path.strip()] request_path = request.scope['path'] # Use raw ASGI path — not spoofable via Host header (CVE-2026-48710) is_allowed = any(request_path == allowed or request_path.startswith(allowed + '/') for allowed in allowed_paths)