spring-projects/spring-security · error · BadCredentialsException

Empty Username

Error message

Empty Username

What it means

AbstractLdapAuthenticationProvider.authenticate() rejects a UsernamePasswordAuthenticationToken whose username is null or blank by throwing BadCredentialsException('Empty Username') before any LDAP call is made. The library treats missing identity as bad credentials rather than a server error.

Source

Thrown at ldap/src/main/java/org/springframework/security/ldap/authentication/AbstractLdapAuthenticationProvider.java:75

	protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

	private boolean useAuthenticationRequestCredentials = true;

	private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

	protected UserDetailsContextMapper userDetailsContextMapper = new LdapUserDetailsMapper();

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
				() -> this.messages.getMessage("LdapAuthenticationProvider.onlySupports",
						"Only UsernamePasswordAuthenticationToken is supported"));
		UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) authentication;
		String username = userToken.getName();
		String password = (String) authentication.getCredentials();
		if (!StringUtils.hasLength(username)) {
			throw new BadCredentialsException(
					this.messages.getMessage("LdapAuthenticationProvider.emptyUsername", "Empty Username"));
		}
		if (!StringUtils.hasLength(password)) {
			throw new BadCredentialsException(
					this.messages.getMessage("AbstractLdapAuthenticationProvider.emptyPassword", "Empty Password"));
		}
		Assert.notNull(password, "Null password was supplied in authentication token");
		DirContextOperations userData = doAuthentication(userToken);
		UserDetails user = this.userDetailsContextMapper.mapUserFromContext(userData, authentication.getName(),
				loadUserAuthorities(userData, authentication.getName(), password));
		return createSuccessfulAuthentication(userToken, user);
	}

	protected abstract DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken auth);

	protected abstract Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData,
			String username, String password);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Validate the username is non-blank in your controller/filter before building the authentication token.
  2. Return a friendly client-side validation error instead of hitting the AuthenticationManager.
  3. If the empty value comes from form binding, configure the binder/filter to reject blank fields early.
  4. Ensure you are not accidentally passing credentials as the principal (wrong constructor argument order).

Example fix

// before
Authentication auth = new UsernamePasswordAuthenticationToken(request.getParameter("user"), request.getParameter("pass"));
manager.authenticate(auth); // Empty Username

// after
String user = request.getParameter("user");
if (user == null || user.isBlank()) {
    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "username is required");
}
Authentication auth = new UsernamePasswordAuthenticationToken(user, request.getParameter("pass"));
manager.authenticate(auth);
Defensive patterns

Strategy: validation

Validate before calling

if (username == null || username.isBlank()) {
    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "username is required");
}

Type guard

static boolean hasUsername(UsernamePasswordAuthenticationToken t) {
    return t != null && t.getName() != null && !t.getName().isBlank();
}

Try / catch

try {
    return authManager.authenticate(token);
} catch (BadCredentialsException e) {
    if ("Empty Username".equals(e.getMessage())) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "username is required");
    }
    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "invalid credentials");
}

Prevention

When it happens

Trigger: Submitting an Authentication to an LdapAuthenticationProvider-backed AuthenticationManager where authentication.getName() is empty — e.g. a login form posted with an empty username field, or a custom Authentication token constructed with a null/blank principal.

Common situations: Frontend allowed empty form submission, API clients omitting the username field in a JSON login payload, custom filters creating UsernamePasswordAuthenticationToken without validating the principal, or whitespace-only input.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/78169c7281b0a945. Report an issue: GitHub.