mirror of
https://github.com/open-webui/open-webui.git
synced 2026-05-06 10:58:17 -05:00
[GH-ISSUE #23973] issue: three backend 500s that should be 200/200/403 (auths session, auths signout, users primary-admin guard) #35665
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @crbender on GitHub (Apr 22, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/23973
Summary
Static code review of
backend/open_webui/routers/auths.pyandbackend/open_webui/routers/users.pyat tagv0.9.1(commit0a8a620fb)surfaced three backend bugs where authenticated or authorized requests
return HTTP 500 instead of the correct response. No authentication or
authorization bypass; these are availability / error-correctness bugs.
Affected version / environment
v0.9.1(tag), commit0a8a620fbmainto observe the bugs)
Bug 1 —
GET /api/v1/auths/returns 500 for cookie-only sessions or malformedAuthorizationheadersLocation
backend/open_webui/routers/auths.py,get_session_userExpected behavior
get_current_useraccepts a JWT from theAuthorizationheader, thetokencookie, orrequest.state.token(set by middleware, e.g. forx-api-key). Any of those should produce a valid session response.Actual behavior
The handler unconditionally dereferences the result of
get_http_authorization_cred():get_http_authorization_credreturnsNonewhen the header is missingor malformed (see
utils/auth.py,get_http_authorization_cred).So any authenticated request that reached this endpoint via cookie (or
with a malformed
Authorizationheader) raisesAttributeError→HTTP 500 instead of the session payload.
Reproduction
:v0.9.1) against any backing store; sign in normallyso you have the
tokencookie.Authorizationheader), send the cookie only:SessionUserInfoResponse.AttributeError: 'NoneType' object has no attribute 'credentials'in server logs).A second reproduction variant: send a malformed header:
Same 500.
Suggested fix
Mirror the token-resolution order used by
get_current_user(header → cookie →request.state.token) and only decode when a token is available:Bug 2 —
GET /api/v1/auths/signoutreturns 500 for malformedAuthorizationheadersLocation
backend/open_webui/routers/auths.py,signoutExpected behavior
Signout should revoke the current token (if present), clear auth cookies,
and return success even when the request has no/invalid
Authorizationheader but a valid
tokencookie.Actual behavior
If the
Authorizationheader is present but malformed,auth_credisNone, the.credentialsaccess raises, and the fallback to the cookienever runs — so the user gets a 500 and their token is not revoked / the
cookies are not cleared.
Reproduction
tokencookie is set.jtiis notadded to the revocation set in Redis.
Suggested fix
Guard the
Noneand always fall back to the cookie:Bug 3 — Primary-admin protection returns 500 instead of 403
Location
backend/open_webui/routers/users.py,update_user_by_idbackend/open_webui/routers/users.py,delete_user_by_idExpected behavior
When an admin tries to edit/delete the primary admin, or when the primary
admin tries to change their own role away from
admin, the server shouldreturn
403 ACTION_PROHIBITED(matches the innerraise HTTPExceptionand the message text).
Actual behavior
The guard lives inside a
try/except Exceptionblock. BecauseHTTPExceptionis anExceptionsubclass, the intentionalis caught by the very next handler and rewritten as
So the client sees a generic 500 for what is actually an authorization
decision, and the server logs contain a misleading
Error checking primary admin status: 403: ...line. Notesignupalready uses the correct pattern (
except HTTPException: raisebeforethe generic catch) — see
routers/auths.py,signup.Reproduction (update)
A(primary, id returned byget_first_user)and
B(second admin).B.403 {"detail": "Action prohibited"}.500 {"detail": "Could not verify primary admin status."}.Same reproduction for the self-demotion path: as
A, POST/{A_ID}/updatewith{"role": "user"}.Reproduction (delete)
B, call:Suggested fix
Re-raise
HTTPExceptionbefore the generic catch in both routes:Proposed diff (if helpful)
A candidate diff exists on this branch:
https://github.com/crbender/open-webui/tree/fix/auth-session-signout-and-primary-admin-guard
It was originally submitted as PR #23972 but auto-closed by
pr-validator-bot(missing CLA section in the body — my mistake). I didnot reopen it because the fixes were drafted from a static review only
and the repo's PR policy asks for PRs to be human-reviewed and manually
tested; filing this as an issue instead so a maintainer can pick up
whichever fix they want in the way they prefer.
Logs / screenshots
Not applicable — these are code-path bugs; the repro commands above are
the logs. I can attach a stack trace from an exercising unit test if a
maintainer wants one.
Related
get_session_user/auth_token.credentials/Could not verify primary admin status.routers/auths.py::signupfor the correctexcept HTTPException: raisepattern already used in this file.@tjbck commented on GitHub (Apr 24, 2026):
Addressed in dev.