|
| 1 | +--- |
| 2 | +title: "Re-enabling login for SSO users (Open Source)" |
| 3 | +description: "Give SSO-provisioned users a local password after moving to Open Source, where SSO is a Pro-only feature" |
| 4 | +audience: opensource |
| 5 | +weight: 2 |
| 6 | +--- |
| 7 | + |
| 8 | +## When this applies |
| 9 | + |
| 10 | +SSO (SAML, OIDC, OAuth) is a [DefectDojo Pro](https://defectdojo.com) feature. If you upgrade to open-source DefectDojo 3.x (or otherwise move off Pro), the SSO login options are removed, and users who were provisioned through SSO can no longer log in. Their accounts were never given a local password, and the UI and API will not let you set one for them: DefectDojo detects them as SSO accounts and blocks the change. |
| 11 | + |
| 12 | +You do **not** need to delete and recreate these users (which would lose their history, permissions, and object ownership). Instead, give each account a local password on the backend and force a password reset on next login. |
| 13 | + |
| 14 | +See the [SSO section](/admin/sso/) and the [3.0 upgrade notes](/releases/os_upgrading/3.0/#sso-providers-are-available-in-defectdojo-pro-only) for background on SSO being Pro-only. |
| 15 | + |
| 16 | +## Why it happens |
| 17 | + |
| 18 | +Open-source DefectDojo authenticates against Django's local user database only. It decides whether an account is an "SSO user" purely by whether the account has a usable password. SSO-provisioned accounts were created with an *unusable* password, so: |
| 19 | + |
| 20 | +* local login fails (there is no password to check), and |
| 21 | +* the **Force password reset** control in the UI and API is blocked, with a message that the user is authorized through SSO. |
| 22 | + |
| 23 | +Setting a real password clears both conditions at once: the account can log in locally, and the forced-reset flag becomes settable. |
| 24 | + |
| 25 | +## The workaround |
| 26 | + |
| 27 | +Run these steps from the Django shell inside the `uwsgi` container: |
| 28 | + |
| 29 | +```bash |
| 30 | +docker compose exec -it uwsgi ./manage.py shell |
| 31 | +``` |
| 32 | + |
| 33 | +### Exmaple for a single user |
| 34 | + |
| 35 | +```python |
| 36 | +from dojo.user.models import Dojo_User, UserContactInfo |
| 37 | + |
| 38 | +u = Dojo_User.objects.get(username="alice@example.com") |
| 39 | +u.set_password("<temporary-strong-password>") # makes the account a local login account |
| 40 | +u.save() |
| 41 | + |
| 42 | +uci, _ = UserContactInfo.objects.get_or_create(user=u) |
| 43 | +uci.force_password_reset = True # force a change on next login |
| 44 | +uci.save() |
| 45 | +``` |
| 46 | + |
| 47 | +## What the user does next |
| 48 | + |
| 49 | +Deliver the temporary password to each user out-of-band (email, your team chat, however you normally share secrets). On their next login, DefectDojo redirects them to the **Change Password** page and will not let them go anywhere else until they set their own password. The forced-reset flag clears automatically once they do. |
| 50 | + |
| 51 | +If your instance has the "I forgot my password" flow enabled (`DD_FORGOT_PASSWORD`, on by default) and email configured, users can instead use the **I forgot my password** link on the login page after their account has a usable password, and set a password without needing the temporary one. |
| 52 | + |
| 53 | +## Notes |
| 54 | + |
| 55 | +* **Kubernetes:** run the shell in the Django pod instead, e.g. `kubectl exec -it deploy/defectdojo-django -c uwsgi -- ./manage.py shell` (adjust the deployment and container names to your release). |
| 56 | +* Choose a strong throwaway password. With `force_password_reset = True` the user cannot keep it, so it only needs to survive one login. |
| 57 | +* Keep at least one working local admin account so you are never locked out. |
0 commit comments