I'm trying to set up security filter chains in a way that both client (session-based user login) and resource_server (key/secret) authentication allow access to a subset of my paths. This is Spring Security 6.
Let's say I want "/actuator/**" to be accessible for either resource_server or client.
What I tried was
@Bean
public SecurityFilterChain authorizeInternal(final HttpSecurity http) throws Exception {
http.oauth2Login(withDefaults());
http.oauth2ResourceServer(withDefaults());
http.authorizeHttpRequests(req -> req
// resource server
.requestMatchers("/actuator/**")
.hasAuthority("SCOPE_read_actuator")
// logged in user
.requestMatchers("/actuator/**")
.hasRole("developer")
);
}
This will prevent both methods from access, which I understand but don't see an alternative.
I also tried around with multiple SecurityFilterChain
s but ended up with pretty much the same problem.
I'm also thinking I could use .access("/actuator/**", authManager)
, but it looks like I'd need to implement something like an OrAuthenticationManager
that checks both my managers' decision.
Am I overlooking an easier way?
If you want to protect a particular URL (or set of URLs) with an "or" rule, you can use AuthorizationManagers.anyOf
.
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasRole;
import static org.springframework.security.authorization.AuthorizationManagers.anyOf;
...
http
// ...
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/actuator/**").access(anyOf(
hasAuthority("SCOPE_read_actuator"),
hasRole("developer")
))
// ...
);
See the Authorize HTTP Requests page in the docs for more info.