spring-projects/spring-security · warning
FilterSecurityInterceptor is configured to reject public…
Error message
FilterSecurityInterceptor is configured to reject public invocations. Your login page may not be accessible.
What it means
During validation, DefaultFilterChainValidator checks whether the configured login page URL would be reachable. If FilterSecurityInterceptor has rejectPublicInvocations=true and no ConfigAttributes are defined for the login request, the login page would be denied, so this warning is logged to alert the developer that login may be inaccessible.
Solutions
- Add an explicit intercept rule permitting the login page (e.g. IS_AUTHENTICATED_ANONYMOUSLY/permitAll) for its URL
- Set rejectPublicInvocations(false) on the FilterSecurityInterceptor
- Migrate to authorizeHttpRequests with .requestMatchers("/login").permitAll(), which avoids the interceptor entirely
Example fix
// before
interceptor.setRejectPublicInvocations(true); // login page has no attributes
// after
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll()
.anyRequest().authenticated()); Defensive patterns
Strategy: validation
Validate before calling
// Verify public URLs are explicitly permitted before enabling rejectPublicInvocations
boolean loginCovered = metadataSource.getAttributes(new FilterInvocation("/login", "GET", null)) != null;
if (rejectPublicInvocations && !loginCovered) { permitLoginUrl(); } Prevention
- Always whitelist login, error, and static resource URLs before denying everything else
- Test unauthenticated access to /login in integration tests
- Avoid rejectPublicInvocations(true) unless the fail-closed behavior is a hard requirement
When it happens
Trigger: checkLoginPageIsPublic finds no attributes for the login page URL in the FilterInvocationSecurityMetadataSource while the FilterSecurityInterceptor is configured to reject public (unsecured) invocations.
Common situations: Setting rejectPublicInvocations(true) on FilterSecurityInterceptor without explicitly defining access rules for the login/error pages; strict 'deny everything not explicitly permitted' configs.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- A filter chain that matches any request
- Can not set rememberMeCookieName and custom…
- Cannot apply to already built object
- Cannot configure both a CorsConfigurationSource and a…
- client_registration_not_found
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/1a5f4b10000a3f46.
Report an issue: GitHub.
Appendix: source
Thrown at config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java:315
private static boolean isFilterSecurityInterceptor(Filter filter) {
return filter instanceof FilterSecurityInterceptor;
}
private static Class<FilterSecurityInterceptor> getFilterSecurityInterceptorClass() {
return FilterSecurityInterceptor.class;
}
private static Boolean checkLoginPageIsPublic(List<Filter> filters, HttpServletRequest loginRequest) {
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
if (authorizationInterceptor == null) {
return null;
}
FilterInvocationSecurityMetadataSource fids = authorizationInterceptor.getSecurityMetadataSource();
Collection<ConfigAttribute> attributes = fids.getAttributes(loginRequest);
if (attributes == null) {
logger.debug("No access attributes defined for login page URL");
if (authorizationInterceptor.isRejectPublicInvocations()) {
logger.warn("FilterSecurityInterceptor is configured to reject public invocations."
+ " Your login page may not be accessible.");
}
return true;
}
return false;
}
private static Supplier<Boolean> getAnonymousCheck(List<Filter> filters, HttpServletRequest loginRequest,
AnonymousAuthenticationToken token) {
FilterSecurityInterceptor authorizationInterceptor = getFilter(FilterSecurityInterceptor.class, filters);
if (authorizationInterceptor == null) {
return null;
}
return () -> {
FilterInvocationSecurityMetadataSource source = authorizationInterceptor.getSecurityMetadataSource();
Collection<ConfigAttribute> attributes = source.getAttributes(loginRequest);
try {
authorizationInterceptor.getAccessDecisionManager().decide(token, loginRequest, attributes);View on GitHub (pinned to 96852e8860)