PacktPublishing / Hands-On-Microservices-with-Spring-Boot-and-Spring-Cloud

Hands-On Microservices with Spring Boot and Spring Cloud, published by Packt
MIT License
464 stars 406 forks source link

Defualt jwtDecoder unable to locate http://auth-server #9

Closed nhtones closed 4 years ago

nhtones commented 4 years ago

The default WebClient used in the default JwtDecoder of composite-product and gateway server implementation does not have access to Eureka server 'names' resulting in a host not found exception for the JWT endpoint at http://auth-server:9999/.well-known/...

To get around this I create a custom implementation of JwtDecoder and injected the LoadBalancing WebClient created at application startup and this resolves the host lookup issues.

SecurityConfig class for composite-product now looks like this:

`@EnableWebFluxSecurity public class SecurityConfig {

@Autowired
private WebClient.Builder webClientBuilder;

@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;

@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http.authorizeExchange().pathMatchers("/actuator/**").permitAll()
            .pathMatchers(HttpMethod.POST, "/product-composite/**").hasAuthority("SCOPE_product:write")
            .pathMatchers(HttpMethod.DELETE, "/product-composite/**").hasAuthority("SCOPE_product:write")
            .pathMatchers(HttpMethod.GET, "/product-composite/**").hasAuthority("SCOPE_product:read").anyExchange()
            .authenticated().and().oauth2ResourceServer().jwt().jwtDecoder(nimbusReactiveJwtDecoder());
    return http.build();
}

@Bean
public NimbusReactiveJwtDecoder nimbusReactiveJwtDecoder() {
    return NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).webClient(webClientBuilder.build()).build();
}

}`

SecurityConfig class for gateway now looks like this:

@EnableWebFluxSecurity public class SecurityConfig {

@Autowired
private WebClient.Builder webClientBuilder;

@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;

@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {

    http.csrf().disable().authorizeExchange().pathMatchers("/headerrouting/**").permitAll()
            .pathMatchers("/actuator/**").permitAll().pathMatchers("/eureka/**").permitAll()
            .pathMatchers("/oauth/**").permitAll().anyExchange().authenticated().and().oauth2ResourceServer().jwt()
            .jwtDecoder(nimbusReactiveJwtDecoder());
    return http.build();
}

@Bean
public NimbusReactiveJwtDecoder nimbusReactiveJwtDecoder() {
    return NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).webClient(webClientBuilder.build()).build();
}

}

magnus-larsson commented 4 years ago

Thanks for reporting this issue!

I'm trying to reproduce the error but I have failed, i.e. everything looks fine when running the tests described in the book.

I have run the following commands (taken from the section "Building and running the automated tests" in chapter 11 in the book):

cd $BOOK_HOME/Chapter11
./gradlew build && docker-compose build
./test-em-all.bash start

The tests run just fine and when trying out the well-known URL required by the composite-product and gateway it also seems ok:

docker run --rm --network=chapter11_default curlimages/curl http://auth-server:9999/.well-known/jwks.json -s | jq .

Returns something like:

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "n": "jv...w"
    }
  ]
}

Can you explain how I can reproduce the error?

nhtones commented 4 years ago

Hi @magnus-larsson , Could be a few things... I'm using Maven dependency management and later framework versions than published in the book i.e. SpringBoot 2.1.3.RELEASE and Spring Cloud Hoxton.SR6

Also running on Windows 10 via corporate proxy.

I've not had any issues following the code examples up to this point (Chapter 10) and the authorisation server being called from product-composite and logging stated something along the lines of 'using default WebClient to access http://auth-server/.wellknown....' which produced an exception relating to host lookup.

Starting the authorisation-server as a standalone app showed that the endpoints were accessible so this lead me to wondering if the WebClient created as default with OAuth2ResourceServer was able to access eureka 'hosts'and I looked to inject the WebClientBuilder knowing it produced a webclient with knowledge of the eureka hosts from earlier chapters.

I'm afraid I can't offer too much insight beyond this. Perhaps its just been a 'feature' introduced by the corporate infrastructure.

magnus-larsson commented 4 years ago

Ok, I see. Thanks for the update!

One issue you need to sort out is the mix of versions used for Spring Boot and Spring Cloud.

If you look at the section "Release Trains" at https://spring.io/projects/spring-cloud you can see that Only Spring Boot 2.2 is compatible with the Spring Cloud Hoxton release.

I'm currently working on upgrading the code base of the book to Spring Boot 2.2.9 and Spring Cloud Hoxton.SR6, due to the long-awaited release of SpringFox 3.0.0. See issue #8 for details. The branch issue8 contains working code based on Spring Boot 2.2.9 and Spring Cloud Hoxton.SR6.

Hope it helps!

nhtones commented 4 years ago

@magnus-larsson - Hi sorry my bad I am using SpringBoot 2.3.1.RELEASE

magnus-larsson commented 4 years ago

Ok :-)

Not sure if Spring Cloud Hoxton currently supports Spring Boot 2.3. Can you try downgrade Spring Boot to 2.2.8 ? That works for in the branch issue8at least!

magnus-larsson commented 4 years ago

While working with issue #8 I have updated the source code to use Spring Boot 2.3.2 and Spring Cloud Hoxton SR6.

Can you check if you still have this problem? I can't reproduce it.

magnus-larsson commented 4 years ago

Closing this issue since I can't reproduce the described problem.