spring-projects/spring-security · warning · CompromisedPasswordException
The provided password is compromised, please change your pas
Error message
The provided password is compromised, please change your password
What it means
DaoAuthenticationProvider.createSuccessAuthentication throws CompromisedPasswordException when a CompromisedPasswordChecker (by default HaveIBeenPwned-backed via CompromisedPasswordChecker instances) reports that the newly presented password appears in known data breaches. This check runs on successful authentication, typically to force rotation of leaked passwords. It is an unchecked AuthenticationException surfaced to the login flow.
Source
Thrown at core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java:133
throw ex;
}
catch (InternalAuthenticationServiceException ex) {
throw ex;
}
catch (Exception ex) {
throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
}
}
@Override
protected Authentication createSuccessAuthentication(Object principal, Authentication authentication,
UserDetails user) {
Assert.notNull(authentication.getCredentials(), "Authentication.getCredentials() cannot be null");
String presentedPassword = authentication.getCredentials().toString();
boolean isPasswordCompromised = this.compromisedPasswordChecker != null
&& this.compromisedPasswordChecker.check(presentedPassword).isCompromised();
if (isPasswordCompromised) {
throw new CompromisedPasswordException("The provided password is compromised, please change your password");
}
String existingEncodedPassword = user.getPassword();
boolean upgradeEncoding = existingEncodedPassword != null
&& !Objects.equals(this.userDetailsPasswordService, UserDetailsPasswordService.NOOP)
&& this.passwordEncoder.get().upgradeEncoding(existingEncodedPassword);
if (upgradeEncoding) {
String newPassword = this.passwordEncoder.get().encode(presentedPassword);
user = this.userDetailsPasswordService.updatePassword(user, newPassword);
}
return super.createSuccessAuthentication(principal, authentication, user);
}
private void prepareTimingAttackProtection() {
if (this.userNotFoundEncodedPassword == null) {
this.userNotFoundEncodedPassword = this.passwordEncoder.get().encode(USER_NOT_FOUND_PASSWORD);
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Ask the user to change their password to a non-compromised value and retry
- Catch CompromisedPasswordException in the login flow and route the user to a forced password-change page
- If breach checking is undesired, disable it by calling .compromisedPasswordChecker(null) / not configuring a checker on the provider
- In offline environments, replace the default checker with a local-list CompromisedPasswordChecker implementation
Example fix
// before DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService); provider.setCompromisedPasswordChecker(new HaveIBeenPwnedRestApiPasswordChecker()); // after (opt out) DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService); provider.setCompromisedPasswordChecker(null); // or handle CompromisedPasswordException with a password-change redirect
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side before submitting
if (commonPasswordList.contains(password)) { show("choose a stronger password"); } Try / catch
try { return authManager.authenticate(token); } catch (CompromisedPasswordException e) { return redirect("/change-password"); } Prevention
- Catch CompromisedPasswordException separately from BadCredentialsException and route users to a password-change flow
- Decide explicitly whether to configure a CompromisedPasswordChecker; document it for users
- In offline environments supply a local compromised-password list implementation
- Enforce strong password rules at registration so stored passwords are unlikely to be breached
When it happens
Trigger: Successful username/password match where the raw password exists in a breach corpus; configuring .compromisedPasswordChecker(...) on DaoAuthenticationProvider (or enabling the default in Spring Boot's form login) and a user logging in with a common/leaked password such as 'Password123'.
Common situations: Applications enabling compromised-password checking for compliance (NIST 800-63B); users with old common passwords tripping the check after the feature was enabled in a Spring Security upgrade; offline corporate environments where the HIBP network call fails or is slow.
Related errors
- RunAsImplAuthenticationProvider.incorrectKey
- Authenticated principal required to operate with ACLs
- CasAuthenticationProvider.incorrectKey
- oidc_provider_not_configured
- Did you forget to add a global <authentication-manager> elem
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/1ee2d493d62a8a39.
Report an issue: GitHub.