onyx
onyx copied to clipboard
SAML user creation fails due to password validation on hashed password
Description:
When a new user logs in via SAML for the first time, or an existing user with a non-web-login role (e.g., EXT_PERM_USER potentially provisioned via external sync) logs in via SAML, the user creation/update process fails with an InvalidPasswordException.
Root Cause: The issue stems from how passwords are handled during the SAML user creation flow:
- The
upsert_saml_userfunction inbackend/ee/onyx/server/saml.pygenerates a random password string usingfastapi_users_pw_helper.generate(). - It then immediately hashes this password using
fastapi_users_pw_helper.hash(). - This hashed password string is passed within the
UserCreateobject to theuser_manager.createmethod. - The
UserManager.createmethod inbackend/onyx/auth/users.pycallsself.validate_passwordon the password provided in theUserCreateobject. -
validate_passwordattempts to apply password complexity rules (checking for length >= 12, uppercase, lowercase, digits, special characters) directly to the hashed password string. - The hashed string fails these complexity checks, leading to the
InvalidPasswordException.
Impact:
- Completely new users cannot be successfully provisioned via SAML login.
- Users who might exist in the database but have roles for which
is_web_login()returnsFalse(likeEXT_PERM_USER) are treated as non-existent during SAML login, triggering the faulty creation path and preventing them from logging in via SAML.
Steps to Reproduce:
- Configure SAML authentication for Onyx.
- Ensure a user either does not exist in the database or exists only with a role where
role.is_web_login()evaluates toFalse. For example, set the user's role to 'EXT_PERM_USER' in the db. - Attempt to log in as this user via the configured SAML Identity Provider.
- Observe the
fastapi_users.exceptions.InvalidPasswordExceptiontraceback in the Onyx backend logs, originating from thevalidate_passwordcall withinUserManager.create.
Suggested Fix:
Modify the upsert_saml_user function in backend/ee/onyx/server/saml.py to pass a raw, compliant password string to UserCreate, instead of a pre-hashed one. The fastapi-users library's create method expects the raw password to perform validation and hashing itself.
Example modification:
# In backend/ee/onyx/server/saml.py -> inside the except exceptions.UserNotExists block within upsert_saml_user
try:
# Generate a password string that complies with validate_password rules
# Example: >=12 chars, upper, lower, digit, special char
compliant_placeholder_password = "SAML_PlaceholderP@ssw0rd123!"
# NOTE: Do NOT hash this here. Pass the raw string.
user: User = await user_manager.create(
UserCreate(
email=email,
password=compliant_placeholder_password, # Pass the RAW compliant password
is_verified=True,
role=role,
)
)
logger.info(f"Successfully created user {email}")
return user
except Exception as e:
# ... existing error handling ...