Issue
I'm using Spring Cloud API Gateway, the app has yaml based configuration and it works well since all routes are internal links, means there is no need for any proxy.
But, there a dependency on Spring Security which is used to validate JWT token and the URL of issuer is the resource that can be reached only via proxy.
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://some-site.com/itmp/v1/.well-known/jwks.json
issuer-uri: https://some-site.com/itmp/v1/
And here is the problem: I can not force WebClient
using the http.proxyHost
parameter. I tried many techniques that I found all around the Internet like setting them implicitly in app properties file, or hard coded in application itself. But nothing worked out for me. Maybe I'm missing something, maybe Spring Cloud has some special tweaks for that behavior?
FYI Project is based on Spring Boot 2.6.6 (reactor-netty 1.0.17 which is normally supports proxyWithSystemProperties
)
Solution
I recently had this exact problem myself. After a lot of back and forth I ended up creating my own ReactiveJwtDecoder
bean and setting the HttpClient
/WebClient
it uses internally (using NimbusReactiveJwtDecoder.webClient(WebClient)
). Something along the lines of:
@Bean
ReactiveJwtDecoder jwtDecoder(@Value("${ISSUER_URI}") String issuerUri,
@Value("${JWKS_URI}") String jwksUri) {
HttpClient httpClient = HttpClient.create().proxyWithSystemProperties();
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
var jwtDecoder = NimbusReactiveJwtDecoder
.withJwkSetUri(jwksUri)
.webClient(webClient)
.build();
// import org.springframework.security.oauth2.jwt.JwtValidators;
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithIssuer(issuerUri));
return jwtDecoder;
}
You can probably inject the OAuth2ResourceServerProperties
-bean instead of those two @Value
-annotated String
s to get the URLs.
Also, be aware that if you application already does more customized JWT claim validation than merely checking iss
, exp
and nbf
, you must remember to inject the existing JwtValidator
and use that instead of the JwtValidators.createDefaultWithIssuer(String)
one.
Answered By - Thomas Kåsene
Answer Checked By - David Marino (JavaFixing Volunteer)