{"record":{"id":"ecb9104284721e1c","repo":"spring-projects/spring-security","slug":"empty-password-ecb910","errorCode":null,"errorMessage":"Empty Password","messagePattern":"Empty Password","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java","lineNumber":72,"sourceCode":"\t * Create an initialized instance using the {@link BaseLdapPathContextSource}\n\t * provided.\n\t * @param contextSource the BaseLdapPathContextSource instance against which bind\n\t * operations will be performed.\n\t */\n\tpublic BindAuthenticator(BaseLdapPathContextSource contextSource) {\n\t\tsuper(contextSource);\n\t}\n\n\t@Override\n\tpublic DirContextOperations authenticate(Authentication authentication) {\n\t\tDirContextOperations user = null;\n\t\tAssert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,\n\t\t\t\t\"Can only process UsernamePasswordAuthenticationToken objects\");\n\t\tString username = authentication.getName();\n\t\tString password = (String) authentication.getCredentials();\n\t\tif (!StringUtils.hasLength(password)) {\n\t\t\tlogger.debug(LogMessage.format(\"Failed to authenticate since no credentials provided\"));\n\t\t\tthrow new BadCredentialsException(\n\t\t\t\t\tthis.messages.getMessage(\"BindAuthenticator.emptyPassword\", \"Empty Password\"));\n\t\t}\n\t\t// If DN patterns are configured, try authenticating with them directly\n\t\tfor (String dn : getUserDns(username)) {\n\t\t\tuser = bindWithDn(dn, username, password);\n\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());","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java#L54-L90","documentation":"BindAuthenticator.authenticate() refuses to perform an LDAP bind when the token's credentials are null or empty, throwing BadCredentialsException('Empty Password'). An empty-password bind is either rejected by the directory or — worse on AD — succeeds as an unauthenticated bind, so the authenticator blocks it explicitly.","triggerScenarios":"Calling LdapAuthenticationProvider/BindAuthenticator.authenticate() with a UsernamePasswordAuthenticationToken whose cast (String) authentication.getCredentials() is null or \"\" — empty login form password, missing JSON field, or token built without credentials.","commonSituations":"REST clients omitting the password property, scripts hitting the login endpoint with only a username, misconfigured serializers dropping null fields, or username/password swapped so credentials ended up empty.","solutions":["Reject empty passwords at the edge (controller/filter) before reaching the AuthenticationManager.","Fix field-name mismatches between the client payload and your DTO so the password is actually populated.","If username/password were swapped in the token constructor, correct the argument order.","Log a debug message and return a generic 400 to avoid revealing which field was empty."],"exampleFix":"// before\nAuthentication auth = new UsernamePasswordAuthenticationToken(username, null);\nauthManager.authenticate(auth); // Empty Password from BindAuthenticator\n\n// after\nif (password == null || password.isEmpty()) {\n    throw new BadCredentialsException(\"credentials required\");\n}\nAuthentication auth = new UsernamePasswordAuthenticationToken(username, password);\nauthManager.authenticate(auth);","handlingStrategy":"validation","validationCode":"if (!(authentication.getCredentials() instanceof String pwd) || pwd.isEmpty()) {\n    throw new BadCredentialsException(\"credentials required\");\n}","typeGuard":"static boolean bindable(UsernamePasswordAuthenticationToken t) {\n    return t.getCredentials() instanceof String s && !s.isEmpty();\n}","tryCatchPattern":"try {\n    return bindAuthenticator.authenticate(token);\n} catch (BadCredentialsException e) {\n    logger.debug(\"bind rejected: {}\", e.getMessage());\n    throw new AuthenticationCredentialsNotFoundException(\"provide username and password\");\n}","preventionTips":["Check token constructor argument order so credentials are not null.","Reject empty passwords in filters/controllers before the provider.","Log BindAuthenticator debug messages to see the empty-password path.","Never allow anonymous/empty binds through your login flow."],"tags":["ldap","bind","empty-password","authentication"],"backgroundTag":"empty-required-field","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"}