{"record":{"id":"1ee2d493d62a8a39","repo":"spring-projects/spring-security","slug":"the-provided-password-is-compromised-please-chang","errorCode":null,"errorMessage":"The provided password is compromised, please change your password","messagePattern":"The provided password is compromised, please change your password","errorType":"exception","errorClass":"CompromisedPasswordException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java","lineNumber":133,"sourceCode":"\t\t\tthrow ex;\n\t\t}\n\t\tcatch (InternalAuthenticationServiceException ex) {\n\t\t\tthrow ex;\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new InternalAuthenticationServiceException(ex.getMessage(), ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected Authentication createSuccessAuthentication(Object principal, Authentication authentication,\n\t\t\tUserDetails user) {\n\t\tAssert.notNull(authentication.getCredentials(), \"Authentication.getCredentials() cannot be null\");\n\t\tString presentedPassword = authentication.getCredentials().toString();\n\t\tboolean isPasswordCompromised = this.compromisedPasswordChecker != null\n\t\t\t\t&& this.compromisedPasswordChecker.check(presentedPassword).isCompromised();\n\t\tif (isPasswordCompromised) {\n\t\t\tthrow new CompromisedPasswordException(\"The provided password is compromised, please change your password\");\n\t\t}\n\t\tString existingEncodedPassword = user.getPassword();\n\t\tboolean upgradeEncoding = existingEncodedPassword != null\n\t\t\t\t&& !Objects.equals(this.userDetailsPasswordService, UserDetailsPasswordService.NOOP)\n\t\t\t\t&& this.passwordEncoder.get().upgradeEncoding(existingEncodedPassword);\n\t\tif (upgradeEncoding) {\n\t\t\tString newPassword = this.passwordEncoder.get().encode(presentedPassword);\n\t\t\tuser = this.userDetailsPasswordService.updatePassword(user, newPassword);\n\t\t}\n\t\treturn super.createSuccessAuthentication(principal, authentication, user);\n\t}\n\n\tprivate void prepareTimingAttackProtection() {\n\t\tif (this.userNotFoundEncodedPassword == null) {\n\t\t\tthis.userNotFoundEncodedPassword = this.passwordEncoder.get().encode(USER_NOT_FOUND_PASSWORD);\n\t\t}\n\t}\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java#L115-L151","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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"],"exampleFix":"// before\nDaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);\nprovider.setCompromisedPasswordChecker(new HaveIBeenPwnedRestApiPasswordChecker());\n// after (opt out)\nDaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);\nprovider.setCompromisedPasswordChecker(null); // or handle CompromisedPasswordException with a password-change redirect","handlingStrategy":"try-catch","validationCode":"// client-side before submitting\nif (commonPasswordList.contains(password)) { show(\"choose a stronger password\"); }","typeGuard":null,"tryCatchPattern":"try { return authManager.authenticate(token); } catch (CompromisedPasswordException e) { return redirect(\"/change-password\"); }","preventionTips":["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"],"tags":["authentication","spring-security","password-policy","breached-password"],"backgroundTag":"compromised-password","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}