Mandib Chaulagain created FINERACT-2961:
-------------------------------------------

             Summary: Submitting the current password is always treated as a 
password change
                 Key: FINERACT-2961
                 URL: https://issues.apache.org/jira/browse/FINERACT-2961
             Project: Apache Fineract
          Issue Type: Bug
          Components: Security, User Management
    Affects Versions: 1.15.0
         Environment: develop @ d4ef406954
            Reporter: Mandib Chaulagain
            Assignee: Mandib Chaulagain
             Fix For: 1.16.0
         Attachments: image-2026-10-16-19-44-54-613.png, 
image-2026-10-16-19-45-27-140.png, image-2026-10-16-19-47-52-513.png, 
image-2026-10-16-19-50-04-971.png, image-2026-10-16-19-50-23-067.png, 
image-2026-10-16-19-54-04-455.png, image-2026-10-16-19-56-22-322.png

If you set a user's password to the one they already have, Fineract treats it 
as a real change. It saves a new hash, adds a row to the password history, 
updates the password's last-updated date and returns {{"password": true}} in 
the response. This only happens when the password reuse check is off, which is 
the default. When the check is on, the fix in FINERACT-2956 rejects the current 
password before it gets this far.

The problem is in {{JsonCommand.isChangeInPasswordParameterNamed}}, which 
checks whether the submitted password is different from the stored one. It 
hashes the submitted password and compares that hash with the stored one using 
{{equals()}}. Fineract uses bcrypt, which adds a new random salt every time it 
hashes, so the two hashes are never equal and the method always returns true. 
It's the same root cause as FINERACT-2956, just in a different method, and PR 
#6670 doesn't touch it.

Steps to reproduce, with the reuse check 
({{password-reuse-check-history-count}}) turned off:

1. Create a user with password A on {{POST /v1/users}}:
 !image-2026-10-16-19-44-54-613.png! 
I got user id 5 back:
 !image-2026-10-16-19-45-27-140.png! 
2. Set the user's last-updated date to a date in the past, so it's easy to see 
if it changes, and check what's stored:
{code:sql}
UPDATE m_appuser SET last_time_password_updated = DATE '2020-01-01' WHERE id = 
5;
SELECT password, last_time_password_updated FROM m_appuser WHERE id = 5;
SELECT id, removal_date FROM m_appuser_previous_password WHERE user_id = 5;
{code}
 !image-2026-10-16-19-47-52-513.png! 
3. Send the same password A again on {{POST /v1/users/5/pwd}}:
 !image-2026-10-16-19-50-04-971.png! 
Response:
 !image-2026-10-16-19-50-23-067.png! 
4. Run the two SELECTs from step 2 again:
 !image-2026-10-16-19-56-22-322.png! 
 !image-2026-10-16-19-54-04-455.png!

I did steps 2 to 4 twice, and each time one more row was added to the history.

The request returns 200 with {{"password": true}} under {{changes}}. In the 
database, the hash is different, {{last_time_password_updated}} has moved from 
2020-01-01 to today, and there's a new history row with the same password in it.

Since the password didn't actually change, I'd expect none of this to happen: 
no password change in the response, and the stored hash, the history and 
{{last_time_password_updated}} left as they were.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to