spring-projects/spring-security · error · IllegalStateException

userDetailsService must be set

Error message

userDetailsService must be set

What it means

KerberosServiceAuthenticationProvider needs a UserDetailsService to turn the validated ticket's username into a UserDetails. It throws IllegalStateException in authenticate() when `userDetailsService` is null.

Source

Thrown at kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/KerberosServiceAuthenticationProvider.java:74

	private static final Log LOG = LogFactory.getLog(KerberosServiceAuthenticationProvider.class);

	private @Nullable KerberosTicketValidator ticketValidator;

	private @Nullable UserDetailsService userDetailsService;

	private UserDetailsChecker userDetailsChecker = new AccountStatusUserDetailsChecker();

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		KerberosServiceRequestToken auth = (KerberosServiceRequestToken) authentication;
		byte[] token = auth.getToken();
		LOG.debug("Try to validate Kerberos Token");
		if (this.ticketValidator == null) {
			throw new IllegalStateException("ticketValidator must be set");
		}
		if (this.userDetailsService == null) {
			throw new IllegalStateException("userDetailsService must be set");
		}
		KerberosTicketValidation ticketValidation = this.ticketValidator.validateTicket(token);
		LOG.debug("Successfully validated " + ticketValidation.username());
		UserDetails userDetails = this.userDetailsService.loadUserByUsername(ticketValidation.username());
		this.userDetailsChecker.check(userDetails);
		additionalAuthenticationChecks(userDetails, auth);
		KerberosServiceRequestToken responseAuth = new KerberosServiceRequestToken(userDetails, ticketValidation,
				userDetails.getAuthorities(), token);
		responseAuth.setDetails(authentication.getDetails());
		return responseAuth;
	}

	@Override
	public boolean supports(Class<? extends Object> auth) {
		return KerberosServiceRequestToken.class.isAssignableFrom(auth);
	}

	@Override

View on GitHub (pinned to 96852e8860)

Solutions

  1. Call setUserDetailsService(...) on the provider (KerberosUserDetailsService works for LDAP-backed or simple setups).
  2. Ensure the UserDetailsService bean exists and is injected.
  3. Validate provider configuration at startup with tests so missing wiring is caught before deployment.

Example fix

// before
provider.setTicketValidator(validator);
// after
provider.setTicketValidator(validator);
provider.setUserDetailsService(new KerberosUserDetailsService());
Defensive patterns

Strategy: validation

Validate before calling

if (provider instanceof KerberosServiceAuthenticationProvider k && k.getUserDetailsService() == null) throw new IllegalStateException("userDetailsService not wired");

Try / catch

try {
  return authenticationManager.authenticate(kerberosToken);
} catch (IllegalStateException e) {
  LOG.error("Provider missing userDetailsService: {}", e.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Processing a KerberosServiceRequestToken with a provider on which setUserDetailsService was never called (after ticketValidator checks pass).

Common situations: SPNEGO setups where the validator is configured but the user-details wiring was omitted, or bean injection failures during context startup.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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