Robin Trietsch
Robin Trietsch

Reputation: 1852

Spring Security Configuration: Basic Auth + Spring Cloud Gateway

I've got a Reactive Spring Boot application, which is responsible for routing requests to downstream services, using Spring Cloud Gateway (i.e. it's an API gateway). The app has some actuator endpoints, that need to be secured, hence I want to use just a simple security for this like basic auth.

I'd like to configure the app, to require requests to /actuator/refresh to be authorized using basic auth (with a configured Spring security user and password). All requests to other endpoints, even if they include basic auth, only need to be passed to the downstream service.

My current Spring security configuration:

@Bean
@Order(1)
SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) {
    http.authorizeExchange(exchanges -> {
        exchanges.matchers(EndpointRequest.toAnyEndpoint().excluding(HealthEndpoint.class, InfoEndpoint.class)).hasRole("ACTUATOR"); // requires Http Basic Auth
    });
    http.httpBasic(withDefaults()); // if not enabled, you cannot get the ACTUATOR role
    return http.build();
}

@Bean
@Order(2)
SecurityWebFilterChain permitAllWebFilterChain(final ServerHttpSecurity http) {
    http.authorizeExchange(exchanges -> exchanges.anyExchange().permitAll()); // allow unauthenticated access to any endpoint (other than secured actuator endpoints?)
    http.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable); // disable Http Basic Auth for all other endpoints
    return http.build();
}

The request meant for the downstream service is not propagated by the API gateway. The spring boot service returns a 401 in this setup, while a 200 is expected / required.

Any ideas why this configuration is not working / how it should be configured otherwise?

Upvotes: 2

Views: 8097

Answers (2)

domminus
domminus

Reputation: 11

From docs:

"Spring Cloud Gateway is built on Spring Boot, Spring WebFlux, and Project Reactor. As a consequence, many of the familiar synchronous libraries (Spring Data and Spring Security, for example) and patterns you know may not apply when you use Spring Cloud Gateway. If you are unfamiliar with these projects, we suggest you begin by reading their documentation to familiarize yourself with some new concepts before working with Spring Cloud Gateway."

This is link to the docs Spring Cloud Docs I had same issue and I could not resolve - this could be related to doc I mentioned.I hope this will help.

Upvotes: 0

Toerktumlare
Toerktumlare

Reputation: 14783

Im not sure what is broken, but have you tried combining them and just have one filter?

@EnableWebFluxSecurity
public class MyExplicitSecurityConfiguration {

    @Bean
    public MapReactiveUserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("user")
            .roles("ACTUATOR")
            .build();
        return new MapReactiveUserDetailsService(user);
    }

    @Bean
    SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) {
        http.authorizeExchange(exchanges -> {
            exchanges.matchers(EndpointRequest.toAnyEndpoint()
                                              .excluding(HealthEndpoint.class, InfoEndpoint.class))
                                              .hasRole("ACTUATOR");
            exchanges.anyExchange().permitAll();
        }).httpBasic(withDefaults());
        return http.build();
    }
}

another good thing could be to enable debug logging and see what fails.

this is done by defining in application.properties

logging.level.org.springframework.security=DEBUG

Upvotes: 1

Related Questions