fusionauth-issues
fusionauth-issues copied to clipboard
Users can't reset password hashed with an unknown algorithm
Users can't reset password hashed with an unknown algorithm
Description
I migrated to FusionAuth from a homegrown system that used the "bcrypt" algorithm to hash passwords. I had a custom password hasher installed in FusionAuth for the transition period, but I removed it recently. The problem is that some of the users hadn't logged in for years, and FusionAuth isn't letting them reset their passwords.
My users see:
FusionAuth encountered an unexpected error. Please review the troubleshooting guide found in the documentation for assistance and the available support channels.
I got this exception in the logs:
2022-08-03 3:20:30.767 PM ERROR io.fusionauth.app.primeframework.error.ExceptionExceptionHandler - An unhandled exception was thrown
io.fusionauth.api.security.UnknownEncryptionSchemeException: Unknown scheme [sha256-bcrypt].
at io.fusionauth.api.security.DefaultPasswordEncryptorLibrary.lookup(DefaultPasswordEncryptorLibrary.java:48)
at io.fusionauth.api.service.connector.FusionAuthConnector.confirmPassword(FusionAuthConnector.java:82)
at io.fusionauth.api.service.connector.FusionAuthConnector.authenticateUserPassword(FusionAuthConnector.java:76)
at io.fusionauth.api.service.connector.FusionAuthConnector.authenticate(FusionAuthConnector.java:58)
at io.fusionauth.api.service.authentication.DefaultAuthenticationService.authenticateUser(DefaultAuthenticationService.java:512)
at io.fusionauth.api.service.authentication.DefaultAuthenticationService.authenticate(DefaultAuthenticationService.java:139)
at io.fusionauth.app.action.api.LoginAction.lambda$post$1(LoginAction.java:136)
at io.fusionauth.app.action.api.BaseLoginAction.callLogin(BaseLoginAction.java:175)
at io.fusionauth.app.action.api.LoginAction.post(LoginAction.java:136)
I was able to work around the problem by logging into the the admin screen, manually setting their password, and requesting a password reset email
Affects versions
v1.36.8
Steps to reproduce
Steps to reproduce the behavior:
- Import a new user with a custom password hashing algorithm
- Remove support for that algorithm from FusionAuth
- Have user try to reset password
- See error
Expected behavior
A password reset doesn't depend on FusionAuth validating the user's old password, so it should just update the password using the new hashing algorithm.
Community guidelines
All issues filed in this repository must abide by the FusionAuth community guidelines.
Thanks, this sure looks like a bug. Appreciate the detailed repro steps!
Follow-up: I tried writing a script to reset all affected users, and I'm running into the same exception trying to call /api/users/change-password.
I would say this is working as designed. If you use a custom password plugin, you cannot remove it until all users have been migrated.
We could be more defensive and allow a password change when the plugin no longer exists, but FusionAuth will never expect a plugin to be removed if you still have users that use that hash.
I would say the bug is not handling this gracefully. Also, I'm not sure why FusionAuth needs to care about the password hashing plugin when trying to reset the password.
Regardless, if this is working as designed, we should:
- not throw an exception in the log
- document it
Also, I'm not sure why FusionAuth needs to care about the password hashing plugin when trying to reset the password.
The exception in the description is during login, perhaps that stack trace is not directly related to the change password workflow. But the login path will fail as well- which is correct.
We could optionally log it, but if you have many users logging in and you remove a plugin, we are going to spam the logs really bad if go do that that route. All the user will see is failed login, and they won't know why. The event logs, or system logs may indicate to an admin that something is broken.
But there are a few cases where we need the current hashing plugin on change.
- If you have configured FusionAuth to disallow the past n passwords.
- If you provide the current password on a change request.
In those two cases, we have to take the provided password in plain text and hash it with the currently configured scheme, or each past scheme to identify if the password has been used before, or if it matches the current value.
We can try to be more defensive, but in the above examples - we have to fail because we will not be able to complete the request w/out the plugin.
For checking the past "n" passwords, I suppose we could log it, create an event log and allow the password to be changed even if we cannot confirm it has not been used before. This is potentially security risk, because FusionAuth will be ignoring a configured policy due to an invalid configuration (missing plugin) which may be surprising.
For checking the current password - I think we'd have to fail that for sure, and the user would have to perform a forgot password workflow or have an admin set their password if their current integration requires a current password during the change request.
But in general - it will always be desirable, and a requirement at least officially that once you are using a custom scheme for password hashing, you have to leave that plugin in place until it is no longer in use.
At a minimum we can fail a bit nicer, and see if we can create an Event Log or something like to let someone know what the issue is.