Skip to content

Refuse registration and passwords while local authentication is disabled - #1103

Merged
DavidMStraub merged 3 commits into
gramps-project:masterfrom
giang17:fix/register-without-local-auth
Oct 24, 2026
Merged

DavidMStraub merged 3 commits into
gramps-project:masterfrom
giang17:fix/register-without-local-auth

Conversation

@giang17

@giang17 giang17 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Closes #778.

Change: With OIDC enabled and OIDC_DISABLE_LOCAL_AUTH set, the endpoints that take a password return 405:

  • registration (POST /api/users/<user_name>/register/, "Registration is disabled"), checked before the tree argument;
  • adding a user, create_owner, changing the password and the password reset (trigger, form and submit), "Local authentication is disabled"; the reset trigger sends no email.

The condition is is_local_auth_disabled() in auth/oidc_helpers.py, now shared by the token, OIDC config, OIDC accounts and user endpoints. It requires OIDC_ENABLED in addition to OIDC_DISABLE_LOCAL_AUTH, as the token endpoint did before: while OIDC is disabled, OIDC_DISABLE_LOCAL_AUTH has no effect on password login.

Tests: One test per endpoint in tests/test_endpoints/test_user.py: with both settings, 405 and no change to users or passwords; with only OIDC_DISABLE_LOCAL_AUTH, the request succeeds. Removing any single check makes its test fail. Full suite without addons installed, as in CI: 2784 passed, 15 skipped.

Drafted with Claude Code (AI assistant).

With OIDC enabled and OIDC_DISABLE_LOCAL_AUTH set, a user registered
with a password could never log in. The register endpoint now returns
405, as with REGISTRATION_DISABLED. Without OIDC the setting has no
effect, as for the token endpoint.

Closes gramps-project#778
@DavidMStraub

Copy link
Copy Markdown
Member

Thanks!

Review suggestion:

  1. Shared helper. is_oidc_enabled() and current_app.config.get("OIDC_DISABLE_LOCAL_AUTH", False) now appears in four places (token.py, oidc_accounts.py, oidc.py, and now user.py). Could we move it into a helper such as is_local_auth_disabled() in auth/oidc_helpers.py? Registration and login need to agree, and copies of the check could drift apart.

  2. Other password flows. Password reset (trigger and reset), change password, create_owner with a password, and admin user creation with a password still accept passwords that can never be used to log in. It would make sense to gate them on the same check, here or in a follow-up PR.

  3. Test. The disabled-case test should also assert that no email is sent (e.g. mock_smtp.assert_not_called()).

  4. Check order. In multi-tree setups, a request without a tree gets a 422 "tree is required" before the disabled check runs. Moving the disabled check first would return 405 consistently.

Move the condition `is_oidc_enabled()` and `OIDC_DISABLE_LOCAL_AUTH`
into `is_local_auth_disabled()` in `auth/oidc_helpers.py` and use it in
the token, OIDC config, OIDC accounts and register endpoints. Tests that
patched `is_oidc_enabled` in the resource modules patch it in
`oidc_helpers` instead.

The register endpoint checks whether registration is disabled before it
requires a tree, so a multi-tree request without a tree also gets 405.
The test checks that no email is sent while registration is disabled.
With OIDC enabled and OIDC_DISABLE_LOCAL_AUTH set, a password can never
be used to log in. Adding a user with a password, create_owner,
changing the password and the password reset (trigger, form and
submit) now return 405, as registration does. The reset trigger sends
no email.
@giang17

giang17 commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

All four points are addressed in d177f2b and 7d2c613.

  1. is_local_auth_disabled() in auth/oidc_helpers.py replaces the four copies in token.py, oidc.py, oidc_accounts.py and user.py. oidc.py read OIDC_DISABLE_LOCAL_AUTH without is_oidc_enabled(), but only after returning early when OIDC is disabled, so the /oidc/config/ response is unchanged. Six tests patched is_oidc_enabled in the resource modules; they now patch it in oidc_helpers, so they still cover the combination of both settings.
  2. abort_if_local_auth_disabled() in user.py returns 405 ("Local authentication is disabled") for adding a user (POST /users/<user_name>/, which requires a password), create_owner, changing the password and the password reset (trigger, form and submit); the trigger sends no email. The status is 405 as for registration; the token endpoint keeps its 403. Bulk creation (POST /users/) takes no passwords and is unchanged. For create_owner, no working path is lost: OIDC logins are matched by sub only (create_or_update_oidc_user), so an owner created there could not log in without local authentication before either. A new setup without local authentication needs an OIDC_GROUP_* mapping for its first owner, as before.
  3. While registration is disabled, the test asserts mock_smtp.assert_not_called(). After the successful registration it asserts that one message was sent, so the first assertion does not pass merely because no email is sent in tests at all.
  4. _is_disabled now runs before the tree check. Without a tree, get_number_users(tree=None, …) counts the owners of all trees. The test posts once without a tree: 405, and 422 with the previous order.

Each new check has a test that fails when the check is removed. Full suite without addons installed, as in CI: 2784 passed, 15 skipped.

Drafted with Claude Code (AI assistant).

@giang17 giang17 changed the title Disable registration when local authentication is disabled Refuse registration and passwords while local authentication is disabled Oct 24, 2026
@DavidMStraub
DavidMStraub merged commit 5eaa440 into gramps-project:master Oct 24, 2026
4 checks passed
@giang17
giang17 deleted the fix/register-without-local-auth branch October 24, 2026 17:11
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.

[Bug] Registration should be disabled when local auth it disabled

2 participants