Skip to content

fix: reject password changes when local auth is disabled - #1041

Open
justadityaraj wants to merge 2 commits into
gotify:masterfrom
justadityaraj:fix/no-password-change-when-localauth-disabled
Open

fix: reject password changes when local auth is disabled#1041
justadityaraj wants to merge 2 commits into
gotify:masterfrom
justadityaraj:fix/no-password-change-when-localauth-disabled

Conversation

@justadityaraj

@justadityaraj justadityaraj commented Aug 29, 2026

Copy link
Copy Markdown

Closes #1040.

Context

The issue reports that the WebUI still offers a "Change Password" prompt when GOTIFY_LOCALAUTH_ENABLED=false. The reporter had not tried going through with it. It turns out the prompt works: UserAPI.ChangePassword never consults the setting, so on an OIDC-only server a user can still set a local password that the login form no longer accepts. SessionAPI.Login already guards on LocalAuthEnabled; this handler was missed.

Changes

Backend:

  • api/user.go: UserAPI gains a LocalAuthEnabled field and ChangePassword aborts with 403 when it is off, mirroring SessionAPI.Login (same status and message shape). The swagger block for this endpoint already documents 403, so docs/spec.json is unchanged.
  • router/router.go: pass conf.LocalAuthEnabled through, as the session handler does.

UI (reworked per review):

  • ui/src/user/Settings.tsx (new): settings page with a theme select (light, dark, system) and the change password form. The form renders disabled when local auth is off; when it is on, it still requires elevation first, same as the dialog did.
  • ui/src/layout/Header.tsx: the account entry stays and always shows the username; it now links to /settings instead of opening the dialog.
  • ui/src/layout/Layout.tsx: adds the /settings route; the header theme toggle and the new select share the same state.
  • ui/src/common/SettingsDialog.tsx: removed, nothing opens it anymore.
  • ui/src/tests/user.test.ts: the change-password test now goes through the new page.

Verification

  • Test_UpdatePassword_LocalAuthDisabled_Expect403 asserts the 403 and that the stored password is untouched. The suite default is now LocalAuthEnabled: true, so the existing password tests are unaffected.
  • This host has no cgo toolchain, so go-sqlite3 is a stub and every UserSuite test fails at testdb.NewDB on master as well; I could not run the suite here. I verified the guard directly with a throwaway test that calls ChangePassword with no database: it returns 403 with the change, and without it the request runs on past that point into the user lookup. CI should exercise the suite test properly.
  • go build ./..., go vet ./api/ ./router/, gofmt -l clean.
  • UI: tsc --noEmit, eslint "src/**/*.{ts,tsx}", prettier --list-different and vite build all clean.

The WebUI offered a "Change Password" prompt even with
GOTIFY_LOCALAUTH_ENABLED=false, and the endpoint behind it accepted the
change: ChangePassword never consulted the setting, so a user on an
OIDC-only server could still set a local password that the login form
no longer accepts.

Guard the handler the same way SessionAPI.Login already does, and hide
the header entry that opens the dialog when local auth is off.

Closes gotify#1040
@justadityaraj
justadityaraj requested a review from a team as a code owner August 29, 2026 21:10
Comment thread ui/src/layout/Header.tsx Outdated
{config.get('localAuth') && (
<ResponsiveButton
icon={<AccountCircle />}
label={name}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place where the currently logged in user is displayed. The button shouldn't be removed. Instead, the button should link to a new "settings" page which includes the Theme setting as select box (light,dark,system). and the change password form which should be disabled when localAuth is disabled.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, the header entry stays and always shows the username. It now links to a new /settings page instead of opening the dialog. The settings page has a theme select (light/dark/system) and the change password form. The form renders disabled when local auth is off; with local auth on it still asks for elevation first, same as the dialog did. SettingsDialog is removed since nothing opens it anymore, and the e2e change-password test goes through the new page now and I left the theme toggle in the header alone; it and the select share the same state.

The header account entry stays as the username display and now links to a new /settings page instead of opening the change password dialog. The page holds a theme select (light, dark, system) and the change password form, rendered disabled when local auth is off. SettingsDialog is removed since nothing opens it anymore.
@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.79%. Comparing base (14bfc25) to head (e52a1da).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1041      +/-   ##
==========================================
+ Coverage   75.77%   75.79%   +0.02%     
==========================================
  Files          66       66              
  Lines        3620     3623       +3     
==========================================
+ Hits         2743     2746       +3     
  Misses        666      666              
  Partials      211      211              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

A server with GOTIFY_LOCALAUTH_ENABLED=false set still allows the user to attempt to change their password

2 participants