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

  1. Verify the header name matches exactly (case-insensitive) what your SSO/gateway sends — check setPrincipalRequestHeader against the actual incoming headers.
  2. Fix the proxy/gateway to forward the identity header (e.g. nginx: proxy_set_header SM_USER $SM_USER;).
  3. Exclude health checks/static paths from the filter via security configuration or setExceptionIfHeaderMissing(false) for endpoints not requiring pre-auth.
  4. Log incoming headers at the app to confirm whether the header is truly absent or the name is wrong.
  5. 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

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


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