Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Security multiple filter chains: match the whole request surface

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A securityMatcher chooses which chain runs; requestMatchers inside that chain only authorize requests it already owns.

Chain selection comes first

A receipt API uses bearer tokens while an operator console uses browser login. Two SecurityFilterChain beans can keep those mechanisms apart. Order the API chain before a final catch-all chain and give it a narrow securityMatcher. If no chain matches a request, Spring Security does not protect it. That is a different failure from a matched request denied by an authorization rule. A typo in an API prefix can therefore expose an endpoint before any hasAuthority check executes.

Include generated endpoints

A chain-scoped matcher also affects endpoints supplied by filters. Form login or logout URLs outside the chain matcher can disappear, producing a 404 rather than an authentication response. Either place those endpoints inside the console path or use a suitable catch-all browser chain. Do not assume a downstream chain contributes its authentication filters to a request that matched an earlier chain; the first matching chain owns that request. Filter order still matters inside each selected chain.

Prove coverage

List every controller, callback, management route and generated login/logout URL. Probe each without credentials, with the wrong credential type and with an authorized identity. Assert that a newly added route falls into a deny-by-default chain. A route inventory test is more reliable than reading a matcher pattern and assuming it covers every method and path.

Implementation contract

Java
@Bean @Order(1)
SecurityFilterChain receiptApi(HttpSecurity http) throws Exception {
    http.securityMatcher("/api/receipts/**")
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults()));
    return http.build();
}
@Bean
SecurityFilterChain remainingRoutes(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(auth -> auth.anyRequest().denyAll());
    return http.build();
}

Cost and verification

Each request tests ordered chain matchers until one matches. A few explicit chains add negligible work, while broad or overlapping patterns raise review cost and can select the wrong credential mechanism.

Common Mistakes

  • Do not leave routes outside every SecurityFilterChain.
  • Do not confuse a chain securityMatcher with authorization requestMatchers.
  • Do not put generated login or logout endpoints outside their owning chain.

Read next

Spring Security filter chain: authentication, CSRF and request order, Spring Security request matchers: order rules and cover the fallback, Spring Security health probes: expose only the health path, Spring Security OAuth2 login: callback, identity and browser session, Spring Security JWT resource server: validate trust before checking scope.

spring
spring-security
security-multiple-filter-chains
Storage details