fix: prevent first-user admin race in LDAP and OAuth registration (#23626)

Both LDAP and OAuth registration checked user count before insert to determine whether to assign admin role.  With multiple workers, concurrent first-user registrations could each see zero users and both create admin accounts.

Applies the insert-first-check-after pattern already used by signup_handler: insert with DEFAULT_USER_ROLE, then atomically check get_num_users()==1 and promote only the sole user to admin.
This commit is contained in:
Classic298
2026-04-12 11:28:41 -05:00
committed by GitHub
parent 36a81ad43b
commit 96a0b3239b
2 changed files with 25 additions and 6 deletions
+9 -3
View File
@@ -479,19 +479,25 @@ async def ldap_auth(
user = Users.get_user_by_email(email, db=db)
if not user:
try:
role = 'admin' if not Users.has_users(db=db) else request.app.state.config.DEFAULT_USER_ROLE
# Insert with default role first to avoid TOCTOU race on
# first-user registration. Matches signup_handler pattern.
user = Auths.insert_new_auth(
email=email,
password=str(uuid.uuid4()),
name=cn,
role=role,
role=request.app.state.config.DEFAULT_USER_ROLE,
db=db,
)
if not user:
raise HTTPException(500, detail=ERROR_MESSAGES.CREATE_USER_ERROR)
# Atomically check if this is the only user *after* the
# insert. Only the single user present should become admin.
if Users.get_num_users(db=db) == 1:
Users.update_user_role_by_id(user.id, 'admin', db=db)
user = Users.get_user_by_id(user.id, db=db)
apply_default_group_assignment(
request.app.state.config.DEFAULT_GROUP_ID,
user.id,