Add Compromised Password Checker

Closes gh-7395
This commit is contained in:
Marcus Hert Da Coregio
2024-03-05 14:45:33 -03:00
parent 89175dfed0
commit 7d66525e23
19 changed files with 1100 additions and 3 deletions

View File

@@ -591,3 +591,99 @@ http {
======
With the above configuration, when a password manager navigates to `/.well-known/change-password`, then Spring Security will redirect to `/update-password`.
[[authentication-compromised-password-check]]
== Compromised Password Checking
There are some scenarios where you need to check whether a password has been compromised, for example, if you are creating an application that deals with sensitive data, it is often needed that you perform some check on user's passwords in order to assert its reliability.
One of these checks can be if the password has been compromised, usually because it has been found in a https://wikipedia.org/wiki/Data_breach[data breach].
To facilitate that, Spring Security provides integration with the https://haveibeenpwned.com/API/v3#PwnedPasswords[Have I Been Pwned API] via the {security-api-url}org/springframework/security/core/password/HaveIBeenPwnedRestApiPasswordChecker.html[`HaveIBeenPwnedRestApiPasswordChecker` implementation] of the {security-api-url}org/springframework/security/core/password/CompromisedPasswordChecker.html[`CompromisedPasswordChecker` interface].
You can either use the `CompromisedPasswordChecker` API by yourself or, if you are using xref:servlet/authentication/passwords/dao-authentication-provider.adoc[the `DaoAuthenticationProvider]` via xref:servlet/authentication/passwords/index.adoc[Spring Security authentication mechanisms], you can provide a `CompromisedPasswordChecker` bean, and it will be automatically picked up by Spring Security configuration.
.Using CompromisedPasswordChecker as a bean
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.httpBasic(withDefaults());
return http.build();
}
@Bean
public CompromisedPasswordChecker compromisedPasswordChecker() {
return new HaveIBeenPwnedRestApiPasswordChecker();
}
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
@Bean
open fun filterChain(http:HttpSecurity): SecurityFilterChain {
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
formLogin {}
httpBasic {}
}
return http.build()
}
@Bean
open fun compromisedPasswordChecker(): CompromisedPasswordChecker {
return HaveIBeenPwnedRestApiPasswordChecker()
}
----
======
By doing that, when you try to authenticate via HTTP Basic or Form Login using a weak password, let's say `123456`, you will receive a 401 response status code.
However, just a 401 is not so useful in that case, it will cause some confusion because the user provided the right password and still was not allowed to log in.
In such cases, you can handle the `CompromisedPasswordException` to perform your desired logic, like redirecting the user-agent to `/reset-password`, for example:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(CompromisedPasswordException.class)
public String handleCompromisedPasswordException(CompromisedPasswordException ex, RedirectAttributes attributes) {
attributes.addFlashAttribute("error", ex.message);
return "redirect:/reset-password";
}
}
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
@ControllerAdvice
class MyControllerAdvice {
@ExceptionHandler(CompromisedPasswordException::class)
fun handleCompromisedPasswordException(ex: CompromisedPasswordException, attributes: RedirectAttributes): RedirectView {
attributes.addFlashAttribute("error", ex.message)
return RedirectView("/reset-password")
}
}
----
======

View File

@@ -8,6 +8,10 @@ Below are the highlights of the release.
- https://spring.io/blog/2024/01/19/spring-security-6-3-adds-passive-jdk-serialization-deserialization-for[blog post] - Added Passive JDK Serialization/Deserialization for Seamless Upgrades
== Authentication
- https://github.com/spring-projects/spring-security/issues/7395[gh-7395] - xref:features/authentication/password-storage.adoc#authentication-compromised-password-check[docs] - Add Compromised Password Checker
== Authorization
- https://github.com/spring-projects/spring-security/issues/14596[gh-14596] - xref:servlet/authorization/method-security.adoc[docs] - Add Programmatic Proxy Support for Method Security