Skip to content

Add DISABLE_PASSWORD_LOGIN to hide local login when OIDC is configured - #240

Merged
alxlion merged 3 commits into
ClaperCo:devfrom
junkerderprovinz:feature/disable-password-login-when-oidc-enabled
Sep 11, 2026
Merged

alxlion merged 3 commits into
ClaperCo:devfrom
junkerderprovinz:feature/disable-password-login-when-oidc-enabled

Conversation

@junkerderprovinz

Copy link
Copy Markdown
Contributor

Summary

#233 asks to disable the local email/password login and keep only OIDC, so systems that already have OIDC set up don't show a confusing second login path.

What this adds

DISABLE_PASSWORD_LOGIN (default false). When set and OIDC is actually configured (OIDC_CLIENT_ID/OIDC_CLIENT_SECRET), it:

  • hides the email/password form, "Forgot your password?" and "Create account" on the login page
  • blocks the login POST and registration POST server-side too, not just a hidden form: the login route refuses the request and redirects to /users/oidc, and the registration route refuses it and redirects home with a flash message
  • if OIDC is not configured, the flag is ignored (with a startup warning) instead of locking everyone out, including the seeded default admin

Admin bootstrap

You raised this yourself in the issue, and I didn't try to auto-solve it. Deciding which identity should inherit admin rights isn't something a PR should assume on your behalf. The sequence I'd document (also in the .env.sample comment I added):

  1. Log in once as the seeded admin@claper.co (or any existing local admin)
  2. Log in once via OIDC as the account that should become the real admin
  3. Promote that OIDC account to admin from the admin panel
  4. Only then set DISABLE_PASSWORD_LOGIN=true

Unrelated fix bundled in

While in UserRegistrationController, I noticed POST /users/register had no ENABLE_ACCOUNT_CREATION check at all, only GET /users/register (the form) did. So registration was possible via a direct POST even with account creation "disabled" in the UI. Fixed the same way, a shared account_creation_allowed?/0 gate on both actions. Happy to split this into its own PR if you'd rather review it separately, flagging it here so it doesn't look buried.

Verification

Live-tested against a real running instance with OIDC configured and the flag on: password form and related links are gone from /users/log_in, a POST with valid password credentials redirects to /users/oidc instead of logging in, and GET /users/register redirects (302) instead of rendering the form.

Ran the real suite in an isolated dev container against this branch specifically (fresh checkout, not a mix of branches): mix format --check-formatted clean, mix test passes 339/339 (336 existing plus 3 new tests for the login-page and login-POST behavior).

Fixes #233

junkerderprovinz added 2 commits August 16, 2026 09:33
Adds DISABLE_PASSWORD_LOGIN (default false). When set and OIDC is
actually configured (OIDC_CLIENT_ID/OIDC_CLIENT_SECRET), the login
page hides the email/password form, the "Forgot your password?" and
"Create account" links, and both the login POST and registration POST
controller actions refuse the request server-side (not just a hidden
form -- the underlying routes are gated too) and send the user to
/users/oidc instead.

If OIDC is not configured, the flag is ignored (with a startup
warning) rather than locking everyone out, including the seeded
default admin.

Admin bootstrap with this enabled: the seeded default admin
(admin@claper.co) is created via a password login that will then be
unusable. Log in once as that seeded admin (or any existing local
admin) before enabling the flag, log in once via OIDC as the account
that should become your real admin, promote that OIDC account to
admin from the admin panel, and only then set
DISABLE_PASSWORD_LOGIN=true. I didn't attempt to automate this step --
deciding which identity inherits admin rights isn't something a PR
should assume on the maintainers' behalf.

Also fixes an unrelated pre-existing gap in the same controller: POST
/users/register had no ENABLE_ACCOUNT_CREATION check at all (only the
GET /users/register that renders the form did), so registration was
possible via a direct POST even with account creation "disabled" in
the UI.

Verified against a real dev instance (compose.dev.yml, isolated
container, torn down after): with OIDC configured and the flag on,
the password form and related links are gone from /users/log_in, a
POST with valid password credentials redirects to /users/oidc instead
of logging in, and GET /users/register redirects (302) instead of
rendering the form.

Fixes ClaperCo#233
:let must come before :if on <.form> per the project's HEEx formatter,
and two lines exceeded the 98-column default.
Change runtime.exs to consider empty or whitespace-only OIDC
credentials as not configured and update the warning text accordingly.
Add runtime_config_test.exs to cover these cases, including empty
secret files. Update user controller tests to exercise
disable_password_login permutations and make session tests run
synchronously. Also adjust Docker dev setup to run ecto.setup and map
Postgres port in compose.dev.yml.
@alxlion

alxlion commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Thanks for the contribution. I reviewed the implementation and pushed a follow-up commit to cover a few edge cases:

  • blank or whitespace-only OIDC credentials no longer risk disabling password login
  • registration POST restrictions now have regression coverage
  • configuration-changing tests now run synchronously
  • runtime configuration is tested with missing credentials and empty secret files

The feature now looks ready from my side.

@alxlion
alxlion merged commit 4d262eb into ClaperCo:dev Sep 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FR: Disable email/password login and keep only OIDC

2 participants