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
- 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.
- Set throwExceptionWhenTokenRejected=false (setRejectWhenTokenRejected) if you want the provider to pass instead of throwing and other providers to be tried.
- Fix the upstream filter config: confirm principalRequestHeader/principalEnvironmentVariable matches the header actually sent by your SSO layer.
- 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
- Keep throwExceptionWhenTokenRejected=false unless you explicitly want fail-fast behavior
- Verify proxies forward identity headers before the filter chain
- Unit-test your pre-auth filter to assert principal/credentials are never null
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No pre-authenticated credentials found in request.
- RunAsImplAuthenticationProvider.incorrectKey
- CasAuthenticationProvider.incorrectKey
- Bad credentials
- Failed to authenticate the one-time token
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/ed52791f98a988e8.
Report an issue: GitHub.