spring-projects/spring-security · error · BadCredentialsException

No pre-authenticated principal found in request.

Error message

No pre-authenticated principal found in request.

What it means

PreAuthenticatedAuthenticationProvider.authenticate() rejects any incoming PreAuthenticatedAuthenticationToken whose principal is null. Because there is no way to authenticate a request without an identity, the provider either throws BadCredentialsException (when throwExceptionWhenTokenRejected is true) or silently returns null, letting the ProviderManager try the next provider.

Source

Thrown at web/src/main/java/org/springframework/security/web/authentication/preauth/PreAuthenticatedAuthenticationProvider.java:95

		Assert.notNull(this.preAuthenticatedUserDetailsService, "An AuthenticationUserDetailsService must be set");
	}

	/**
	 * Authenticate the given PreAuthenticatedAuthenticationToken.
	 * <p>
	 * If the principal contained in the authentication object is null, the request will
	 * be ignored to allow other providers to authenticate it.
	 */
	@Override
	public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
		if (!supports(authentication.getClass())) {
			return null;
		}
		logger.debug(LogMessage.format("PreAuthenticated authentication request: %s", authentication));
		if (authentication.getPrincipal() == null) {
			logger.debug("No pre-authenticated principal found in request.");
			if (this.throwExceptionWhenTokenRejected) {
				throw new BadCredentialsException("No pre-authenticated principal found in request.");
			}
			return null;
		}
		if (authentication.getCredentials() == null) {
			logger.debug("No pre-authenticated credentials found in request.");
			if (this.throwExceptionWhenTokenRejected) {
				throw new BadCredentialsException("No pre-authenticated credentials found in request.");
			}
			return null;
		}
		UserDetails userDetails = this.preAuthenticatedUserDetailsService
			.loadUserDetails((PreAuthenticatedAuthenticationToken) authentication);
		this.userDetailsChecker.check(userDetails);
		Collection<GrantedAuthority> authorities = new LinkedHashSet<>(userDetails.getAuthorities());
		authorities.addAll(this.grantedAuthoritySupplier.get());
		PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(userDetails,
				authentication.getCredentials(), authorities);
		result.setDetails(authentication.getDetails());

View on GitHub (pinned to 96852e8860)

Solutions

  1. Ensure the pre-auth source (header, request attribute, J2EE principal) is actually present before the token reaches the provider — verify proxies/load balancers forward the identity header.
  2. Set throwExceptionWhenTokenRejected=false (setRejectWhenTokenRejected) if you want the provider to pass instead of throwing and other providers to be tried.
  3. Fix the upstream filter config: confirm principalRequestHeader/principalEnvironmentVariable matches the header actually sent by your SSO layer.
  4. In tests, construct the token with a non-null principal: new PreAuthenticatedAuthenticationToken("user", "creds").

Example fix

// before
provider.setThrowExceptionWhenTokenRejected(true); // hard failure on missing principal
// after
provider.setThrowExceptionWhenTokenRejected(false); // skip provider, no exception
Defensive patterns

Strategy: validation

Validate before calling

if (token.getPrincipal() == null) {
    throw new IllegalStateException("Pre-auth token has no principal; check upstream header/filter config");
}
provider.authenticate(token);

Type guard

boolean hasPrincipal = (auth != null && auth.getPrincipal() != null);

Prevention

When it happens

Trigger: Calling authenticate() with a PreAuthenticatedAuthenticationToken built via new PreAuthenticatedAuthenticationToken(null, credentials) or a token whose details mapper produced no principal, while throwExceptionWhenTokenRejected=true.

Common situations: A header/attribute-extraction filter (e.g. RequestHeaderAuthenticationFilter) is deployed behind a proxy that strips the identity header, so the token is created with a null principal; a custom AuthenticationUserDetailsSsoService/filter returns null when the SSO attribute is absent; unit tests construct a token without a principal and enable throwExceptionWhenTokenRejected.

Understand the failure class

Related errors


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