spring-projects/spring-security · warning

Anonymous access to the login page doesn't appear to be enab

Error message

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)

What it means

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.

Source

Thrown at config/src/main/java/org/springframework/security/config/http/DefaultFilterChainValidator.java:237

			return;
		}
		if (checkLoginPageIsPublic(filters, loginRequest)) {
			return;
		}
		AnonymousAuthenticationFilter anonymous = getFilter(AnonymousAuthenticationFilter.class, filters);
		if (anonymous == null) {
			this.logger.warn("The login page is being protected by the filter chain, but you don't appear to have"
					+ " anonymous authentication enabled. This is almost certainly an error.");
			return;
		}
		// Simulate an anonymous access with the supplied attributes.
		AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", anonymous.getPrincipal(),
				anonymous.getAuthorities());
		Supplier<Boolean> check = deriveAnonymousCheck(filters, loginRequest, token);
		try {
			boolean allowed = check.get();
			if (!allowed) {
				this.logger.warn("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)");
			}
		}
		catch (Exception ex) {
			// May happen legitimately if a filter-chain request matcher requires more
			// request data than that provided
			// by the dummy request used when creating the filter invocation. See SEC-1878
			this.logger.info("Unable to check access to the login page to determine if anonymous access is allowed. "
					+ "This might be an error, but can happen under normal circumstances.", ex);
		}
	}

	private boolean checkLoginPageIsPublic(List<Filter> filters, HttpServletRequest loginRequest) {
		if (USING_ACCESS) {
			Boolean isPublic = AccessComponents.checkLoginPageIsPublic(filters, loginRequest);
			if (isPublic != null) {
				return isPublic;

View on GitHub (pinned to 96852e8860)

Solutions

  1. Add requestMatchers("/login").permitAll() as the first authorization rule for the actual login URL.
  2. Check authorization rule ordering: permitAll entries must precede anyRequest().authenticated().
  3. Inspect custom filters for behavior that rejects anonymous tokens on the login path.
  4. Enable debug logging for FilterChainProxy and trace the simulated request to see which filter denies it.

Example fix

// before: login page still protected
http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
    .formLogin(f -> f.loginPage("/login"));
// after: explicit anonymous access
http.authorizeHttpRequests(a -> a.requestMatchers("/login").permitAll()
        .anyRequest().authenticated())
    .formLogin(f -> f.loginPage("/login"));
Defensive patterns

Strategy: validation

Validate before calling

// simulated anonymous access in tests
mockMvc.perform(get("/login").anonymous())
    .andExpect(status().isOk());

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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