[ 
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)

Reply via email to