Content
View differences
Updated by Oliver Günther 5 days ago
**As a** system administrator running OpenProject with SSO
**I want to** control who may sign in with an internal username/password
**so that** users linked to an identity provider cannot bypass SSO with a leftover password, while still allowing break-glass access when needed
**Acceptance criteria**
* A new Password login policy is available under _Administration → Authentication → Login and registration → Single Sign-On (SSO)_ with three modes:
* Allow for everyone (`all`, default)
* _this matches the — current behaviour without any env_
* Disallow for SSO users (`except_sso`)
* _users — users linked to an OmniAuth provider cannot authenticate with an internal/LDAP password; fixes the reported bug when this mode is enabled_
enabled
* Disallow for everyone (`none`)
* _password — password form hidden on_ `_/login_`_; on `/login`; only allowlisted principals may use a password_
password
* In `except_sso` and `none`, administrators can configure Users and groups who may still use a password (break-glass allowlist)
* selecting groups there will result in child groups to be included as well
* `/login/internal` remains available for break-glass password login when direct SSO login is configured and/or when mode is `none` and an allowlist (or env login overlay) exists
* Password authentication, password changes, lost-password flows, and LDAP admin are blocked according to the active policy
* Legacy `OPENPROJECT_DISABLE__PASSWORD__LOGIN=true` (and `disable_password_login` in configuration) maps to mode `none` and locks the UI setting.
* A note is added so that configurations should prefer `OPENPROJECT_PASSWORD__LOGIN`
* When settings are provided via environment/configuration, the admin UI shows a banner listing non-editable settings
* Deleting a user or group removes them from the break-glass allowlist automatically
* If no SSO provider is enabled, password-login restriction controls are disabled with an explanatory warning
**Technical notes**
* Policy is implemented via `Users::PasswordLogin` and setting `password_login` (`all` / `except_sso` / `none`); see [PR #24991](https://github.com/opf/openproject/pull/24991)
* `OpenProject::Configuration[]` reads from `Settings::Definition`; legacy `disable_password_login` still feeds into `password_login` default/writable lambdas in `definition.rb`
* Password writes for affected users are rejected at the contract layer, not only at login
* Break-glass config: `password_login_bypass_principal_ids` (users/groups, admin UI) and `password_login_bypass_logins` (env overlay, case-insensitive)
* Login enforcement goes through `User#password_login_allowed?` / `check_password?`; admin password edits go through `Users::BaseContract`
* SSO tab UI is behind the Enterprise `sso_auth_providers` guard; configuration via env/yml works regardless
* Original work package: <mention class="mention" data-id="61159" data-type="work_package" data-text="##SC-99" data-display-id="SC-99">##SC-99</mention>
**Permissions and visibility considerations**
* _To whom is this feature visible?_
Administrators with access to _Authentication_ settings (Enterprise for the SSO UI tab). End users see effects on login (hidden password form, blocked login, `/login/internal` when applicable).
* _When is it not visible?_
When no SSO provider is configured (controls disabled + warning). When settings are env-locked (shown read-only with banner). LDAP connections menu hidden when password login is fully disabled (`none`). Password-related admin settings disabled in `none` mode.
**Translation considerations**
* _Key terms and phrases in the key languages_
* EN: Password login · Allow for everyone · Disallow for SSO users · Disallow for everyone · Users and groups who may still use a password
* DE: Passwort-Anmeldung · Für alle zulassen · Für SSO-Benutzer verbieten · Für alle verbieten · Benutzer und Gruppen, die weiterhin ein Passwort verwenden dürfen _(Crowdin sync expected)_
* FR: Connexion par mot de passe · Autoriser pour tout le monde · Interdire pour les utilisateurs SSO · Interdire pour tout le monde · Utilisateurs et groupes autorisés à utiliser un mot de passe _(Crowdin sync expected)_
* New strings live in `config/locales/en.yml` under `setting_password_login_*` and `settings.authentication.*`; allowlist wording uses “allowlist” in docs/comments, “Users and groups who may still use a password” in UI
**Out of scope**
* Full dual-mode UX where SSO-linked users can actively manage, recover, and use passwords alongside SSO (the “non-simple” option from the original report)
* Changing OmniAuth account-remapping behaviour (`oauth_allow_remapping_of_existing_users`)
* Restricting API/basic-auth or non-password authentication mechanisms
* Auto-enabling `except_sso` on existing instances (default remains `all`)
**I want to** control who may sign in with an internal username/password
**so that** users linked to an identity provider cannot bypass SSO with a leftover password, while still allowing break-glass access when needed
**Acceptance criteria**
* A new Password login policy is available under _Administration → Authentication → Login and registration → Single Sign-On (SSO)_ with three modes:
* Allow for everyone (`all`, default)
* _this matches the
* _users
* _password
* selecting groups there will result in child groups to be included as well
* `/login/internal` remains available for break-glass password login when direct SSO login is configured and/or when mode is `none` and an allowlist (or env login overlay) exists
* Password authentication, password changes, lost-password flows, and LDAP admin are blocked according to the active policy
* Legacy `OPENPROJECT_DISABLE__PASSWORD__LOGIN=true` (and `disable_password_login` in configuration) maps to mode `none` and locks the UI setting.
* A note is added so that configurations should prefer `OPENPROJECT_PASSWORD__LOGIN`
* When settings are provided via environment/configuration, the admin UI shows a banner listing non-editable settings
* Deleting a user or group removes them from the break-glass allowlist automatically
* If no SSO provider is enabled, password-login restriction controls are disabled with an explanatory warning
**Technical notes**
*
* `OpenProject::Configuration[]` reads from `Settings::Definition`; legacy `disable_password_login` still feeds into `password_login` default/writable lambdas in `definition.rb`
* Password writes for affected users are rejected at the contract layer, not only at login
* Break-glass config: `password_login_bypass_principal_ids` (users/groups, admin UI) and `password_login_bypass_logins` (env overlay, case-insensitive)
* Login enforcement goes through `User#password_login_allowed?` / `check_password?`; admin password edits go through `Users::BaseContract`
* SSO tab UI is behind the Enterprise `sso_auth_providers` guard; configuration via env/yml works regardless
*
**Permissions and visibility considerations**
* _To whom is this feature visible?_
Administrators with access to _Authentication_ settings (Enterprise for the SSO UI tab). End users see effects on login (hidden password form, blocked login, `/login/internal` when applicable).
* _When is it not visible?_
When no SSO provider is configured (controls disabled + warning). When settings are env-locked (shown read-only with banner). LDAP connections menu hidden when password login is fully disabled (`none`). Password-related admin settings disabled in `none` mode.
**Translation considerations**
* _Key terms and phrases in the key languages_
* EN: Password login · Allow for everyone · Disallow for SSO users · Disallow for everyone · Users and groups who may still use a password
* DE: Passwort-Anmeldung · Für alle zulassen · Für SSO-Benutzer verbieten · Für alle verbieten · Benutzer und Gruppen, die weiterhin ein Passwort verwenden dürfen _(Crowdin sync expected)_
* FR: Connexion par mot de passe · Autoriser pour tout le monde · Interdire pour les utilisateurs SSO · Interdire pour tout le monde · Utilisateurs et groupes autorisés à utiliser un mot de passe _(Crowdin sync expected)_
* New strings live in `config/locales/en.yml` under `setting_password_login_*` and `settings.authentication.*`; allowlist wording uses “allowlist” in docs/comments, “Users and groups who may still use a password” in UI
**Out of scope**
* Full dual-mode UX where SSO-linked users can actively manage, recover, and use passwords alongside SSO (the “non-simple” option from the original report)
* Changing OmniAuth account-remapping behaviour (`oauth_allow_remapping_of_existing_users`)
* Restricting API/basic-auth or non-password authentication mechanisms
* Auto-enabling `except_sso` on existing instances (default remains `all`)