A securityMatcher chooses which chain runs; requestMatchers inside that chain only authorize requests it already owns.
Spring Security multiple filter chains: match the whole request surface
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
@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.
