fix(auth): clear force-reset flag when password is written outside web flow#337
fix(auth): clear force-reset flag when password is written outside web flow#337level09 wants to merge 1 commit into
Conversation
…b flow The force-password-reset Redis flag is cleared by Flask-Security's password_changed signal, which only fires through the web /change form. CLI password resets and admin user-edit writes bypassed the signal, leaving the flag set after a fresh password was written. The user would then be redirected to /change on every request indefinitely. Centralize password writes through User.set_password(), which hashes and clears the flag together. Update flask reset, reset-all-passwords, and User.from_json to use it. New-user creation paths are unchanged since no flag can exist for an unsaved user.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
apodacaduron
left a comment
There was a problem hiding this comment.
Tested locally — Redis flag gets cleared correctly from CLI reset, admin UI, and reset-all-passwords behaves as expected too, no regressions
Summary
Admin-triggered force-password-reset uses a Redis flag (
security:user:<id>) checked by a globalbefore_app_requestguard that redirects every request to/changeuntil the user updates their password. The flag is cleared by Flask-Security'spassword_changedsignal, but that signal only fires through the web/changeform. CLI password resets (flask reset,flask reset-all-passwords) and the admin user-edit endpoint write a fresh hash directly and skip the signal, so the flag persists. The user then sees a successful login but is stuck in a redirect loop because the flag never clears.Fix
User.set_password(password)which hashes the password and clears the force-reset Redis flag in one step.resetandreset_all_passwordscommands andUser.from_jsonthrough it.reset_all_passwordsstill callsset_security_reset_key()afterward, since its purpose is to issue a temporary password and force the user to change it.install,create) are unchanged. They build aUserbefore save, so noidand no flag can exist.The web
/changeflow is untouched and continues to clear the flag via the existingpassword_changedsignal handler.Test plan
flask reset -u <user> -p <new>and confirm the user can access non-/changepages on next login.flask reset-all-passwordsstill leaves the force-reset flag set so all users must change their passwords on next login./changeflow still clears the flag (regression check).