{"record":{"id":"827bef577ce4dfb8","repo":"spring-projects/spring-security","slug":"bad-credentials","errorCode":null,"errorMessage":"Bad credentials","messagePattern":"Bad credentials","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java","lineNumber":154,"sourceCode":"\t\tAssert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,\n\t\t\t\t() -> this.messages.getMessage(\"AbstractUserDetailsAuthenticationProvider.onlySupports\",\n\t\t\t\t\t\t\"Only UsernamePasswordAuthenticationToken is supported\"));\n\t\tString username = determineUsername(authentication);\n\t\tboolean cacheWasUsed = true;\n\t\tUserDetails user = this.userCache.getUserFromCache(username);\n\t\tif (user == null) {\n\t\t\tcacheWasUsed = false;\n\t\t\ttry {\n\t\t\t\tuser = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);\n\t\t\t}\n\t\t\tcatch (UsernameNotFoundException ex) {\n\t\t\t\tthis.logger.debug(LogMessage.format(\"Failed to find user '%s'\", username));\n\t\t\t\tString message = this.messages.getMessage(\"AbstractUserDetailsAuthenticationProvider.badCredentials\",\n\t\t\t\t\t\t\"Bad credentials\");\n\t\t\t\tif (!this.hideUserNotFoundExceptions) {\n\t\t\t\t\tthrow ex;\n\t\t\t\t}\n\t\t\t\tthrow new BadCredentialsException(message, ex);\n\t\t\t}\n\t\t\tAssert.notNull(user, \"retrieveUser returned null - a violation of the interface contract\");\n\t\t}\n\t\ttry {\n\t\t\tperformPreCheck(user, (UsernamePasswordAuthenticationToken) authentication);\n\t\t}\n\t\tcatch (AuthenticationException ex) {\n\t\t\tif (!cacheWasUsed) {\n\t\t\t\tthrow ex;\n\t\t\t}\n\t\t\t// There was a problem, so try again after checking\n\t\t\t// we're using latest data (i.e. not from the cache)\n\t\t\tcacheWasUsed = false;\n\t\t\tuser = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);\n\t\t\tperformPreCheck(user, (UsernamePasswordAuthenticationToken) authentication);\n\t\t}\n\t\tthis.postAuthenticationChecks.check(user);\n\t\tif (!cacheWasUsed) {","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/core/src/main/java/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.java#L136-L172","documentation":"AbstractUserDetailsAuthenticationProvider.authenticate() catches UsernameNotFoundException from retrieveUser() and, when hideUserNotFoundExceptions is true (the default), rethrows it as BadCredentialsException 'Bad credentials'. This deliberately hides whether the username exists to prevent user-enumeration attacks.","triggerScenarios":"DaoAuthenticationProvider.authenticate() with a username not found by the UserDetailsService (mapped to Bad credentials), or BadCredentialsException thrown directly by an incorrect password comparison in additionalAuthenticationChecks.","commonSituations":"Typo in username OR wrong password; DaoAuthenticationProvider with default hideUserNotFoundExceptions=true; custom UserDetailsService throwing UsernameNotFoundException that gets masked; users expecting 'user not found' but seeing 'Bad credentials'.","solutions":["Verify the username exists and the password is correct — the message intentionally conflates both","Call setHideUserNotFoundExceptions(false) on DaoAuthenticationProvider during debugging to surface the real UsernameNotFoundException","Enable debug logging for org.springframework.security to see 'Failed to find user' vs password mismatch","Check encoding/matching: PasswordEncoder must match how passwords were stored (e.g. BCryptPasswordEncoder for bcrypt hashes)"],"exampleFix":"// before (debugging)\nDaoAuthenticationProvider p = new DaoAuthenticationProvider(uds);\n// after\nDaoAuthenticationProvider p = new DaoAuthenticationProvider(uds);\np.setHideUserNotFoundExceptions(false); // surfaces UsernameNotFoundException during troubleshooting only","handlingStrategy":"try-catch","validationCode":"try { uds.loadUserByUsername(username); } catch (UsernameNotFoundException e) { log.debug(\"User not found\"); } // combined with a PasswordEncoder check in tests\nPasswordEncoder pe = PasswordEncoderFactories.createDelegatingPasswordEncoder();\nassert pe.matches(rawPassword, storedPassword);","typeGuard":"boolean credentialsPlausible(String username, String raw, UserDetails u, PasswordEncoder pe) { return username != null && !username.isBlank() && pe.matches(raw, u.getPassword()); }","tryCatchPattern":"try { authMgr.authenticate(token); } catch (BadCredentialsException e) { return ResponseEntity.status(401).body(\"Invalid username or password\"); }","preventionTips":["Ensure the PasswordEncoder matches how passwords are stored","Keep hideUserNotFoundExceptions=true in production to avoid user enumeration","Check username spelling/case and account existence before escalating to support","Enable debug logging when troubleshooting, not in production"],"tags":["spring-security","bad-credentials","login"],"backgroundTag":"invalid-credentials","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}