{"record":{"id":"e65a89f1427e8a46","repo":"spring-projects/spring-security","slug":"principalrequestheader-header-not-found-in-requ","errorCode":null,"errorMessage":"${principalRequestHeader} header not found in request.","messagePattern":"(.+?) header not found in request\\.","errorType":"exception","errorClass":"PreAuthenticatedCredentialsNotFoundException","httpStatus":null,"severity":"error","filePath":"web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java","lineNumber":65,"sourceCode":"public class RequestHeaderAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {\n\n\tprivate String principalRequestHeader = \"SM_USER\";\n\n\tprivate @Nullable String credentialsRequestHeader;\n\n\tprivate boolean exceptionIfHeaderMissing = true;\n\n\t/**\n\t * Read and returns the header named by {@code principalRequestHeader} from the\n\t * request.\n\t * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and\n\t * {@code exceptionIfHeaderMissing} is set to {@code true}.\n\t */\n\t@Override\n\tprotected @Nullable Object getPreAuthenticatedPrincipal(HttpServletRequest request) {\n\t\tString principal = request.getHeader(this.principalRequestHeader);\n\t\tif (principal == null && this.exceptionIfHeaderMissing) {\n\t\t\tthrow new PreAuthenticatedCredentialsNotFoundException(\n\t\t\t\t\tthis.principalRequestHeader + \" header not found in request.\");\n\t\t}\n\t\treturn principal;\n\t}\n\n\t/**\n\t * Credentials aren't usually applicable, but if a {@code credentialsRequestHeader} is\n\t * set, this will be read and used as the credentials value. Otherwise a dummy value\n\t * will be used.\n\t */\n\t@Override\n\tprotected @Nullable Object getPreAuthenticatedCredentials(HttpServletRequest request) {\n\t\tif (this.credentialsRequestHeader != null) {\n\t\t\treturn request.getHeader(this.credentialsRequestHeader);\n\t\t}\n\t\treturn \"N/A\";\n\t}\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/web/src/main/java/org/springframework/security/web/authentication/preauth/RequestHeaderAuthenticationFilter.java#L47-L83","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@Bean\npublic RequestHeaderAuthenticationFilter filter() {\n    RequestHeaderAuthenticationFilter f = new RequestHeaderAuthenticationFilter();\n    f.setPrincipalRequestHeader(\"SM_USER\"); // gateway sends \"SM_USERDN\"\n    return f;\n}\n// after\n@Bean\npublic RequestHeaderAuthenticationFilter filter() {\n    RequestHeaderAuthenticationFilter f = new RequestHeaderAuthenticationFilter();\n    f.setPrincipalRequestHeader(\"SM_USERDN\"); // matches header sent by gateway\n    return f;\n}","handlingStrategy":"try-catch","validationCode":"if (request.getHeader(principalRequestHeader) == null) {\n    throw new PreAuthenticatedCredentialsNotFoundException(principalRequestHeader + \" header not found in request.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    chain.doFilter(request, response);\n} catch (PreAuthenticatedCredentialsNotFoundException e) {\n    logger.warn(\"Missing pre-auth header\", e);\n    response.sendError(HttpServletResponse.SC_FORBIDDEN);\n}","preventionTips":["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"],"tags":["spring-security","preauth","http-header","sso"],"backgroundTag":"missing-required-argument","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}