From 627e8aaa42a4cdbf6ce402401be0ab8bc594e755 Mon Sep 17 00:00:00 2001 From: silentoplayz Date: Sun, 7 Jun 2026 16:29:27 -0400 Subject: [PATCH] perf(auth): make verify_password non-blocking with asyncio.to_thread --- backend/open_webui/models/auths.py | 2 +- backend/open_webui/routers/auths.py | 17 +++++++++++++---- backend/open_webui/utils/auth.py | 19 ++++++++++--------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/backend/open_webui/models/auths.py b/backend/open_webui/models/auths.py index 5e363352bd..8d8e9e4f4f 100644 --- a/backend/open_webui/models/auths.py +++ b/backend/open_webui/models/auths.py @@ -148,7 +148,7 @@ class AuthsTable: credential = await session.get(Auth, resolved.id) if not credential or not credential.active: return - if not verify_password(credential.password): + if not await verify_password(credential.password): return return resolved diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 434a6349de..61b866dbf1 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -290,9 +290,12 @@ async def update_password( if WEBUI_AUTH_TRUSTED_EMAIL_HEADER: raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.ACTION_PROHIBITED) if session_user: + async def _verify(pw): + return await verify_password(form_data.password, pw) + user = await Auths.authenticate_user( session_user.email, - lambda pw: verify_password(form_data.password, pw), + _verify, db=db, ) @@ -621,10 +624,13 @@ async def signin( admin_email = 'admin@localhost' admin_password = 'admin' + async def _verify_admin(pw): + return await verify_password(admin_password, pw) + if await Users.get_user_by_email(admin_email.lower(), db=db): user = await Auths.authenticate_user( admin_email.lower(), - lambda pw: verify_password(admin_password, pw), + _verify_admin, db=db, ) else: @@ -641,7 +647,7 @@ async def signin( user = await Auths.authenticate_user( admin_email.lower(), - lambda pw: verify_password(admin_password, pw), + _verify_admin, db=db, ) else: @@ -660,9 +666,12 @@ async def signin( # decode safely — ignore incomplete UTF-8 sequences form_data.password = password_bytes.decode('utf-8', errors='ignore') + async def _verify_signin(pw): + return await verify_password(form_data.password, pw) + user = await Auths.authenticate_user( form_data.email.lower(), - lambda pw: verify_password(form_data.password, pw), + _verify_signin, db=db, ) diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py index 26cea6b45f..a5a7687858 100644 --- a/backend/open_webui/utils/auth.py +++ b/backend/open_webui/utils/auth.py @@ -176,15 +176,16 @@ def validate_password(password: str) -> bool: return True -def verify_password(plain_password: str, hashed_password: str) -> bool: - """Verify a password against its hash""" - return ( - bcrypt.checkpw( - plain_password.encode('utf-8'), - hashed_password.encode('utf-8'), - ) - if hashed_password - else None +async def verify_password(plain_password: str, hashed_password: str) -> bool: + """Verify a password against its hash in a thread pool (non-blocking).""" + import asyncio + + if not hashed_password: + return None + return await asyncio.to_thread( + bcrypt.checkpw, + plain_password.encode('utf-8'), + hashed_password.encode('utf-8'), )