Document Upgrading Password Encoding

Closes gh-17112

Signed-off-by: Mark Putsiata <m.putsiata@gmail.com>
This commit is contained in:
Mark Putsiata 2025-05-15 22:54:11 +02:00
parent e30dc42d1e
commit 465e13ae3d
1 changed files with 51 additions and 0 deletions

View File

@ -689,3 +689,54 @@ class CompromisedPasswordAuthenticationFailureHandler : AuthenticationFailureHan
} }
---- ----
====== ======
[[authentication-upgrading-password-encoding]]
== Upgrading Password Encoding
Spring Security can automatically upgrade existing password encodings without asking users to reset their passwords. It uses the `PasswordEncoder.upgradeEncoding(String)` method to determine whether a stored password should be re-encoded for improved security.
If `PasswordEncoder.upgradeEncoding(String)` indicates an update is needed and a `UserDetailsPasswordService` bean is available, the framework will rehash the password immediately after a successful login. The raw password submitted at login is passed to `PasswordEncoder` to produce a stronger encoding. The `UserDetailsPasswordService` saves the newly encoded password in the user store (e.g., database or LDAP) and returns the updated `UserDetails`.
To enable this behavior, simply define a `UserDetailsPasswordService` bean. You can always provide your own `UserDetailsPasswordService` implementation tailored to your persistent user store.
For example, if you are using a `UserDetailsManager`, you can write:
.Using UserDetailsPasswordService with UserDetailsManager
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
UserDetailsPasswordService userDetailsPasswordService(UserDetailsManager userDetailsManager) {
return (user, newPassword) -> {
UserDetails updated = User.withUserDetails(user)
.password(newPassword)
.build();
userDetailsManager.updateUser(updated);
return updated;
};
}
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
@Bean
open fun userDetailsPasswordService(userDetailsManager: UserDetailsManager): UserDetailsPasswordService {
return UserDetailsPasswordService { user, newPassword ->
val updated = User.withUserDetails(user)
.password(newPassword)
.build()
userDetailsManager.updateUser(updated)
updated
}
}
----
======
When using xref:servlet/authentication/passwords/jdbc.adoc#servlet-authentication-jdbc-bean[JdbcUserDetailsManager], you do not need to register a separate `UserDetailsPasswordService` bean, since `JdbcUserDetailsManager` already implements that interface. You simply enable the upgrade mechanism by calling `JdbcUserDetailsManager.setEnableUpdatePassword(true)`.
This approach lets you migrate from weaker hashes to stronger algorithms (like <<authentication-password-storage-bcrypt,bcrypt>>) without impacting your users. Passwords are re-encoded only after successful authentication, enabling a gradual, transparent migration for your application.