{"record":{"id":"94befdadd1b33f9c","repo":"spring-projects/spring-security","slug":"anonymous-access-to-the-login-page-doesn-t-appear","errorCode":null,"errorMessage":"Anonymous access to the login page doesn't appear to be enabled. This is almost certainly an error. Please check your configuration allows unauthenticated access to the configured login page. (Simulated access was rejected)","messagePattern":"Anonymous access to the login page doesn't appear to be enabled\\. This is almost certainly an error\\. Please check your configuration allows unauthenticated access to the configured login page\\. \\(Simulated access was rejected\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java","lineNumber":237,"sourceCode":"\t\t\treturn;\n\t\t}\n\t\tif (checkLoginPageIsPublic(filters, loginRequest)) {\n\t\t\treturn;\n\t\t}\n\t\tAnonymousAuthenticationFilter anonymous = getFilter(AnonymousAuthenticationFilter.class, filters);\n\t\tif (anonymous == null) {\n\t\t\tthis.logger.warn(\"The login page is being protected by the filter chain, but you don't appear to have\"\n\t\t\t\t\t+ \" anonymous authentication enabled. This is almost certainly an error.\");\n\t\t\treturn;\n\t\t}\n\t\t// Simulate an anonymous access with the supplied attributes.\n\t\tAnonymousAuthenticationToken token = new AnonymousAuthenticationToken(\"key\", anonymous.getPrincipal(),\n\t\t\t\tanonymous.getAuthorities());\n\t\tSupplier<Boolean> check = deriveAnonymousCheck(filters, loginRequest, token);\n\t\ttry {\n\t\t\tboolean allowed = check.get();\n\t\t\tif (!allowed) {\n\t\t\t\tthis.logger.warn(\"Anonymous access to the login page doesn't appear to be enabled. \"\n\t\t\t\t\t\t+ \"This is almost certainly an error. Please check your configuration allows unauthenticated \"\n\t\t\t\t\t\t+ \"access to the configured login page. (Simulated access was rejected)\");\n\t\t\t}\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\t// May happen legitimately if a filter-chain request matcher requires more\n\t\t\t// request data than that provided\n\t\t\t// by the dummy request used when creating the filter invocation. See SEC-1878\n\t\t\tthis.logger.info(\"Unable to check access to the login page to determine if anonymous access is allowed. \"\n\t\t\t\t\t+ \"This might be an error, but can happen under normal circumstances.\", ex);\n\t\t}\n\t}\n\n\tprivate boolean checkLoginPageIsPublic(List<Filter> filters, HttpServletRequest loginRequest) {\n\t\tif (USING_ACCESS) {\n\t\t\tBoolean isPublic = AccessComponents.checkLoginPageIsPublic(filters, loginRequest);\n\t\t\tif (isPublic != null) {\n\t\t\t\treturn isPublic;","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java#L219-L255","documentation":"DefaultFilterChainValidator.checkLoginPageIsntProtected simulates anonymous access to the configured login page by replaying the filter chain with an AnonymousAuthenticationToken. If the simulated invocation is rejected, it warns that anonymous access to the login page is not actually enabled despite an anonymous filter being present, i.e. some filter or authorization rule still blocks unauthenticated users.","triggerScenarios":"Calling validate() when the anonymous filter exists but deriveAnonymousCheck's simulated access is denied: an authorization rule or a filter (e.g. a strict RequestMatcher-based chain, CSRF, or custom filter) rejects the anonymous request to the login URL.","commonSituations":"Login page matched by a chained request matcher requiring authentication; permitAll rules placed after an anyRequest().authenticated() in the wrong order; custom filters throwing on anonymous tokens; multiple http blocks intercepting the login URL.","solutions":["Add requestMatchers(\"/login\").permitAll() as the first authorization rule for the actual login URL.","Check authorization rule ordering: permitAll entries must precede anyRequest().authenticated().","Inspect custom filters for behavior that rejects anonymous tokens on the login path.","Enable debug logging for FilterChainProxy and trace the simulated request to see which filter denies it."],"exampleFix":"// before: login page still protected\nhttp.authorizeHttpRequests(a -> a.anyRequest().authenticated())\n    .formLogin(f -> f.loginPage(\"/login\"));\n// after: explicit anonymous access\nhttp.authorizeHttpRequests(a -> a.requestMatchers(\"/login\").permitAll()\n        .anyRequest().authenticated())\n    .formLogin(f -> f.loginPage(\"/login\"));","handlingStrategy":"validation","validationCode":"// simulated anonymous access in tests\nmockMvc.perform(get(\"/login\").anonymous())\n    .andExpect(status().isOk());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Place permitAll rules for public pages before anyRequest().authenticated().","Keep custom filters no-op-friendly for anonymous tokens on public paths.","Test each public URL with both anonymous and authenticated mocks.","Enable org.springframework.security debug logging in dev to trace simulated access."],"tags":["spring-security","filter-chain","anonymous-authentication","authorization"],"backgroundTag":"invalid-config-value","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"}