onyx icon indicating copy to clipboard operation
onyx copied to clipboard

SAML user creation fails due to password validation on hashed password

Open ThomaciousD opened this issue 1 year ago • 0 comments

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:

  1. The upsert_saml_user function in backend/ee/onyx/server/saml.py generates a random password string using fastapi_users_pw_helper.generate().
  2. It then immediately hashes this password using fastapi_users_pw_helper.hash().
  3. This hashed password string is passed within the UserCreate object to the user_manager.create method.
  4. The UserManager.create method in backend/onyx/auth/users.py calls self.validate_password on the password provided in the UserCreate object.
  5. validate_password attempts to apply password complexity rules (checking for length >= 12, uppercase, lowercase, digits, special characters) directly to the hashed password string.
  6. 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() returns False (like EXT_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:

  1. Configure SAML authentication for Onyx.
  2. Ensure a user either does not exist in the database or exists only with a role where role.is_web_login() evaluates to False. For example, set the user's role to 'EXT_PERM_USER' in the db.
  3. Attempt to log in as this user via the configured SAML Identity Provider.
  4. Observe the fastapi_users.exceptions.InvalidPasswordException traceback in the Onyx backend logs, originating from the validate_password call within UserManager.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 ...

ThomaciousD avatar Apr 14 '25 09:04 ThomaciousD