From 5cf95d2c0f7af27bcc604ce2d19f2109c8b52da3 Mon Sep 17 00:00:00 2001 From: VincentLambert Date: Tue, 14 Jul 2026 17:30:35 +0200 Subject: [PATCH] Fix: admin password update crashes for SSO users (500 'NoneType' object has no attribute 'split') (#16914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What problem does this PR solve? Setting a password from the admin panel for an SSO-provisioned account (OIDC/OAuth/GitHub) returns a **500** with: ``` 'NoneType' object has no attribute 'split' ``` **Root cause** — SSO-provisioned accounts have no local password, so `usr.password` is `None` (the `User.password` column is `null=True`). In `UserMgr.update_user_password` (`admin/server/services.py`), the "same password" optimization calls: ```python if check_password_hash(usr.password, psw): ``` `werkzeug.security.check_password_hash(None, psw)` internally does `pwhash.split("$")`, which raises `AttributeError: 'NoneType' object has no attribute 'split'` → surfaced as a 500. **Repro** 1. Configure an SSO channel (OIDC/OAuth) under `oauth` in the service config. 2. Log in once via SSO so the account is auto-provisioned (created without a local password). 3. In the admin panel, set/change that user's password. 4. → 500 `'NoneType' object has no attribute 'split'`. **Fix** — guard the equality check with `usr.password`. A passwordless (SSO) user skips the comparison and goes straight to setting the new password, which is the desired behavior (it gives them a password fallback in addition to SSO). ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Co-authored-by: Claude Opus 4.8 (1M context) --- admin/server/services.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/server/services.py b/admin/server/services.py index 754d690b50..67a4e52f36 100644 --- a/admin/server/services.py +++ b/admin/server/services.py @@ -117,7 +117,9 @@ class UserMgr: # check new_password different from old. usr = user_list[0] psw = decrypt(new_password) - if check_password_hash(usr.password, psw): + # SSO-provisioned users (OIDC/OAuth) have no local password (usr.password is None): + # skip the equality check, which would otherwise crash inside werkzeug's split(). + if usr.password and check_password_hash(usr.password, psw): return "Same password, no need to update!" # update password UserService.update_user_password(usr.id, psw)