[
https://issues.apache.org/jira/browse/FINERACT-2956?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mandib Chaulagain resolved FINERACT-2956.
-----------------------------------------
Resolution: Fixed
> Password reuse check never rejects a previously used password
> -------------------------------------------------------------
>
> Key: FINERACT-2956
> URL: https://issues.apache.org/jira/browse/FINERACT-2956
> Project: Apache Fineract
> Issue Type: Bug
> Components: Security, User Management
> Affects Versions: 1.15.0, 1.16.0
> Environment: develop @ d4ef406954 (bug also present on current
> develop 999e7a704d), PostgreSQL 18.3, JDK 25, default tenant, no other
> configuration changes.
> Reporter: Mandib Chaulagain
> Assignee: Mandib Chaulagain
> Priority: Major
> Fix For: 1.17.0
>
> Attachments: image-2026-10-15-21-56-06-601.png,
> image-2026-10-15-21-56-20-210.png, image-2026-10-15-21-56-30-851.png,
> image-2026-10-15-21-57-03-681.png, image-2026-10-15-21-57-15-817.png,
> image-2026-10-15-21-57-33-625.png, image-2026-10-15-21-57-50-357.png,
> image-2026-10-15-21-57-59-635.png, image-2026-10-15-21-58-31-389.png,
> image-2026-10-15-21-59-10-033.png
>
>
> Fineract has a setting, {{{}password-reuse-check-history-count{}}}, that is
> supposed to stop users from setting a password they have used before (added
> in FINERACT-2005). When the setting is turned on, it does not work. Fineract
> accepts an old password, and it also accepts the same password the user
> already has.
> Here are the steps to reproduce:
> # Turn on the check. On {{PUT /v1/configurations/name/\{configName\}}} with
> configName {{password-reuse-check-history-count}}, send this body ({{"value":
> 3}} means the last 3 passwords can't be reused):
> !image-2026-10-15-21-56-06-601.png!
> Here's the response body:
> !image-2026-10-15-21-56-20-210.png!
> A GET on the same setting confirms it is enabled with value 3:
> !image-2026-10-15-21-56-30-851.png!
> # Create a test user. On {{POST /v1/users}}, I used the following request
> body (this is the first time the password is set, call it password A):
> !image-2026-10-15-21-57-03-681.png!
> And got this response (user id 4):
> !image-2026-10-15-21-57-15-817.png!
> # Change to a new password, B, on {{POST /v1/users/4/pwd}} (second time a
> password is given):
> !image-2026-10-15-21-57-33-625.png!
> The response was 200, which is correct.
> # Reuse the old password A again (third time a password is given):
> !image-2026-10-15-21-57-50-357.png!
> *Actual:* 200, the password is changed.
> !image-2026-10-15-21-57-59-635.png!
> *Expected:* 400 {{error.msg.password.already.used}}, because A is one of the
> last 3 passwords.
> # Resend the body from step 4, so A is set while A is already the current
> password (fourth time a password is given):
> !image-2026-10-15-21-58-31-389.png!
> *Actual:* 200 again.
> *Expected:* 400 {{error.msg.password.already.used}}.
> In
> {{AppUserWritePlatformServiceJpaRepositoryImpl.getCurrentPasswordToSaveAsPreview()}},
> the new password is hashed and compared with each old hash using
> {{String.equals}}. Fineract hashes passwords with bcrypt, which adds a random
> salt every time, so the same password never produces the same hash string.
> The comparison can never be true.
> The database shows this. For user 4, the history holds testingasdhjS202@ (set
> at creation), asdklj@Wfasdsdf989 and testingasdhjS202@, and the current
> password is testingasdhjS202@. Three of the four hashes are the same
> password, and still all of them are different strings:
> !image-2026-10-15-21-59-10-033.png!
> There is a second problem. The current password is never checked, because it
> is only saved to the history table ({{m_appuser_previous_password}}) after it
> has been replaced.
> The existing unit test does not catch this because it uses a fake encoder
> that always returns "encoded".
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)