diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 5e054596c..8d7581dd4 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -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, diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index 8aaadc271..100df7a21 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -1109,9 +1109,12 @@ class OAuthManager: log.debug('Assigning the only user the admin role') return 'admin' if not user and user_count == 0: - # If there are no users, assign the role "admin", as the first user will be an admin - log.debug('Assigning the first user the admin role') - return 'admin' + # First-user bootstrap: skip role management gating so the + # instance can be initialized. We intentionally return the + # default role here (not 'admin') — admin promotion happens + # race-safely *after* insert via get_num_users() == 1. + log.debug('First user bootstrap: using default role (admin promotion deferred to post-insert)') + return auth_manager_config.DEFAULT_USER_ROLE if auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT: log.debug('Running OAUTH Role management') @@ -1577,6 +1580,16 @@ class OAuthManager: 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 to avoid TOCTOU race on first-user registration. + # Matches signup_handler pattern. + 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) + if auth_manager_config.WEBHOOK_URL: await post_webhook( WEBUI_NAME,