Search code examples
javaspring-security

How to allow both resource server and client login for an endpoint?


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 SecurityFilterChains 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?


Solution

  • 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.