{"record":{"id":"f6f71c5853178d75","repo":"spring-projects/spring-security","slug":"bad-credentials-f6f71c","errorCode":null,"errorMessage":"Bad credentials","messagePattern":"Bad credentials","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java","lineNumber":96,"sourceCode":"\t\t\tif (user != null) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (user == null) {\n\t\t\tlogger.debug(LogMessage.of(() -> \"Failed to bind with any user DNs \" + getUserDns(username)));\n\t\t}\n\t\t// Otherwise use the configured search object to find the user and authenticate\n\t\t// with the returned DN.\n\t\tif (user == null && getUserSearch() != null) {\n\t\t\tlogger.trace(\"Searching for user using \" + getUserSearch());\n\t\t\tDirContextOperations userFromSearch = getUserSearch().searchForUser(username);\n\t\t\tuser = bindWithDn(userFromSearch.getDn().toString(), username, password, userFromSearch.getAttributes());\n\t\t\tif (user == null) {\n\t\t\t\tlogger.debug(\"Failed to find user using \" + getUserSearch());\n\t\t\t}\n\t\t}\n\t\tif (user == null) {\n\t\t\tthrow new BadCredentialsException(\n\t\t\t\t\tthis.messages.getMessage(\"BindAuthenticator.badCredentials\", \"Bad credentials\"));\n\t\t}\n\t\treturn user;\n\t}\n\n\tprivate @Nullable DirContextOperations bindWithDn(String userDnStr, String username, String password) {\n\t\treturn bindWithDn(userDnStr, username, password, null);\n\t}\n\n\tprivate @Nullable DirContextOperations bindWithDn(String userDnStr, String username, String password,\n\t\t\t@Nullable Attributes attrs) {\n\t\tBaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();\n\t\tName userDn = LdapUtils.newLdapName(userDnStr);\n\t\tName fullDn = LdapUtils.prepend(userDn, ctxSource.getBaseLdapName());\n\t\tlogger.trace(LogMessage.format(\"Attempting to bind as %s\", fullDn));\n\t\tDirContext ctx = null;\n\t\ttry {\n\t\t\tctx = getContextSource().getContext(fullDn.toString(), password);","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java#L78-L114","documentation":"BindAuthenticator.authenticate() throws BadCredentialsException('Bad credentials') when every configured strategy — DN patterns and user search — failed to produce an authenticated user (bindWithDn/bindWithSearch returned null or the user could not be found). It is the generic LDAP 'wrong username or password' answer, deliberately vague.","triggerScenarios":"All DN patterns fail to bind (wrong password or DN template doesn't match the entry), and the user search either finds no entry or its bind fails; after the loop, user remains null and this exception is thrown.","commonSituations":"UserSearchBase or userDnPatterns misconfigured so the entry is never found, account locked/disabled or password expired in the directory, password typo, or LDAP server refusing binds for the search principal so lookup silently fails.","solutions":["Verify userDnPatterns / UserSearch base and filter resolve to the actual directory entry (test with ldapsearch).","Confirm the user's account is enabled and the password is correct by binding manually with ldapwhoami.","Check the context source's manager DN/password are valid — a failing search context makes lookups return nothing.","Enable DEBUG logging for BindAuthenticator ('Failed to find user using ...') to see which strategy failed.","Confirm URL/port of the LdapContextSource and that TLS (ldaps/StartTLS) matches the directory's requirements."],"exampleFix":"// before\nauthenticator.setUserDnPatterns(new String[] {\"uid={0},ou=wrong,dc=example,dc=org\"});\nauthManager.authenticate(token); // Bad credentials\n\n// after\nauthenticator.setUserDnPatterns(new String[] {\"uid={0},ou=people,dc=example,dc=org\"});\n// or use search:\nLdapUserSearch search = new FilterBasedLdapUserSearch(\"ou=people\", \"(uid={0})\", contextSource);\nauthenticator.setUserSearch(search);\nauthManager.authenticate(token);","handlingStrategy":"try-catch","validationCode":"// sanity-check LDAP config at startup\nAssert.hasText(contextSource.getBase(), \"base DN must be set\");\ntry (DirContext ctx = contextSource.getContext(managerDn, managerPassword)) {\n    ctx.search(\"ou=people\", \"(objectClass=person)\", new SearchControls()); // search path works\n}","typeGuard":null,"tryCatchPattern":"try {\n    return authManager.authenticate(token);\n} catch (BadCredentialsException e) {\n    logger.debug(\"LDAP bind failed for user lookup\");\n    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, \"invalid username or password\");\n}","preventionTips":["Test userDnPatterns and user-search filters with ldapsearch before wiring them in.","Verify manager DN/password; a broken search context makes all users 'not found'.","Enable DEBUG logging on BindAuthenticator to see which strategy failed.","Check account state (locked/expired) in the directory, not just the password."],"tags":["ldap","bind","bad-credentials","authentication"],"backgroundTag":"authentication-required","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"}