spring-projects/spring-security · error · PreAuthenticatedCredentialsNotFoundException
${principalRequestHeader} header not found in request.
Error message
${principalRequestHeader} header not found in request. What it means
RequestHeaderAuthenticationFilter.getPreAuthenticatedPrincipal() reads the user identity from the HTTP request header named by principalRequestHeader. If the header is missing and exceptionIfHeaderMissing is true (the default), it throws PreAuthenticatedCredentialsNotFoundException so the normal authentication-failure handling kicks in; if false it returns null and the request proceeds without pre-auth identity.
Source
Thrown at web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java:65
public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
private String principalRequestHeader = "SM_USER";
private @Nullable String credentialsRequestHeader;
private boolean exceptionIfHeaderMissing = true;
/**
* Read and returns the header named by {@code principalRequestHeader} from the
* request.
* @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and
* {@code exceptionIfHeaderMissing} is set to {@code true}.
*/
@Override
protected @Nullable Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String principal = request.getHeader(this.principalRequestHeader);
if (principal == null && this.exceptionIfHeaderMissing) {
throw new PreAuthenticatedCredentialsNotFoundException(
this.principalRequestHeader + " header not found in request.");
}
return principal;
}
/**
* Credentials aren't usually applicable, but if a {@code credentialsRequestHeader} is
* set, this will be read and used as the credentials value. Otherwise a dummy value
* will be used.
*/
@Override
protected @Nullable Object getPreAuthenticatedCredentials(HttpServletRequest request) {
if (this.credentialsRequestHeader != null) {
return request.getHeader(this.credentialsRequestHeader);
}
return "N/A";
}
View on GitHub (pinned to 96852e8860)
Solutions
- Verify the header name matches exactly (case-insensitive) what your SSO/gateway sends — check setPrincipalRequestHeader against the actual incoming headers.
- Fix the proxy/gateway to forward the identity header (e.g. nginx: proxy_set_header SM_USER $SM_USER;).
- Exclude health checks/static paths from the filter via security configuration or setExceptionIfHeaderMissing(false) for endpoints not requiring pre-auth.
- Log incoming headers at the app to confirm whether the header is truly absent or the name is wrong.
- Restrict network access so the app is reachable only through the component that injects the header.
Example fix
// before
@Bean
public RequestHeaderAuthenticationFilter filter() {
RequestHeaderAuthenticationFilter f = new RequestHeaderAuthenticationFilter();
f.setPrincipalRequestHeader("SM_USER"); // gateway sends "SM_USERDN"
return f;
}
// after
@Bean
public RequestHeaderAuthenticationFilter filter() {
RequestHeaderAuthenticationFilter f = new RequestHeaderAuthenticationFilter();
f.setPrincipalRequestHeader("SM_USERDN"); // matches header sent by gateway
return f;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (request.getHeader(principalRequestHeader) == null) {
throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader + " header not found in request.");
} Try / catch
try {
chain.doFilter(request, response);
} catch (PreAuthenticatedCredentialsNotFoundException e) {
logger.warn("Missing pre-auth header", e);
response.sendError(HttpServletResponse.SC_FORBIDDEN);
} Prevention
- Whitelist health-check/static paths from pre-auth enforcement
- Confirm reverse proxy config forwards the identity header (proxy_set_header)
- Log all incoming request headers once in staging to catch header-name mismatches early
When it happens
Trigger: A request reaches RequestHeaderAuthenticationFilter without the configured header (e.g. 'SM_USER', 'REMOTE_USER') while exceptionIfHeaderMissing=true — e.g. a health check, direct browser access, or a proxy stripping the header.
Common situations: Reverse proxy or load balancer (nginx, ALB) not forwarding the SSO header; header name typo/mismatch between gateway and filter config; container monitoring probes hitting the app directly without going through the SSO site; SSO agent down.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ${principalEnvironmentVariable} variable not found in reques
- invalid_request
- invalid_token
- invalid_request
- invalid_token
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/e65a89f1427e8a46.
Report an issue: GitHub.