Expected Behavior
No timeout.
Current Behavior
Caused by: java.lang.IllegalStateException: com.nimbusds.jose.RemoteKeySourceException: Couldn't retrieve remote JWK set: Read timed out
at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getSignatureAlgorithms(JwtDecoderProviderConfigurationUtils.java:107)
at org.springframework.security.oauth2.jwt.JwtDecoders.withProviderConfiguration(JwtDecoders.java:122)
at org.springframework.security.oauth2.jwt.JwtDecoders.fromOidcIssuerLocation(JwtDecoders.java:66)
Context
I am using Spring Security 5.5.3
Our team set up some JWT Decoder by utilizing JwtDecoders like this:
@Bean
JwtDecoder jwtDecoder() {
final NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)
JwtDecoders.fromOidcIssuerLocation(issuer);
final OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(apiAudience);
final OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
final OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
In the current implementation, I see it is now trying to obtain signature algorithms and it possibly can cause timeout.
I already tried to look around, but the answer is not good enough. This similar discussion https://github.com/spring-projects/spring-security/issues/4474 seems left hanging. This stackoverflow thread has hacky solution. This one also is not conclusive.
Comment From: jgrandja
@andreas-trvlk Please see the reference doc on how to configure timeouts.
I'll close this as answered.
Comment From: vishal423
@jgrandja, I believe you have overlooked the problem reported over here. JwtDecoders doesn't provide a way to specify the timeout and if you try to rewrite the custom JwtDecoders code, then, you will notice the underlying JwtDecoderProviderConfigurationUtils class has package visibility.
I think the problem reported over here and also in the linked JHipster issue comes from the below line of code. The current implementation doesn't specify the ResourceRetriever bean object as the 2nd constructor argument of RemoteJWKSet and thus internally defaults to DefaultResourceRetriever bean object with connection and read timeouts as 500ms.
private static JwtDecoder withProviderConfiguration(Map<String, Object> configuration, String issuer) {
...
RemoteJWKSet<SecurityContext> jwkSource = new RemoteJWKSet(url(jwkSetUri));
...
}
Can we extend JwtDecoders class to provide a method to allow specification of RestOperations and ResourceRetriever as input parameters?
Comment From: jgrandja
@vishal423 Please see comment. There are no references to JwtDecoders?
I believe you have overlooked the problem reported over here.
JwtDecodersdoesn't provide a way to specify the timeout and if you try to rewrite the customJwtDecoderscode
If you link through to the referenced sample code, the solution is provided:
@Bean
public JwtDecoder jwtDecoder(RestTemplateBuilder builder) {
RestOperations rest = builder
.setConnectTimeout(Duration.ofSeconds(60))
.setReadTimeout(Duration.ofSeconds(60))
.build();
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri(jwkSetUri).restOperations(rest).build();
return jwtDecoder;
}
Comment From: vishal423
@jgrandja, In the sample code, you are expected to have jwkSetUri to build the JwtDecoder, however, the issue raised is for JwtDecoders trying to create a JwtDecoder from oidc issuerUri using the fromOidcIssuerLocation factory method. Unless I missed something, you can't pass a timeout to that factory method.
Comment From: jgrandja
@vishal423 JwtDecoders does not fulfill all use cases, e.g. you cannot configure timeouts. It's designed as a utility for simple/convenient use cases. For more advanced use cases, e.g. configure timeouts, you need to explicitly create/configure the NimbusJwtDecoder as mentioned in previous comment.
Comment From: vishal423
@jgrandja , I feel the default 500ms as connect/read timeout is too small in a low bandwidth usage scenario and we should update that to a more reasonable number.
I also tried to write custom JwtDecoders with configurable timeouts, however, noted that the underlying used JwtDecoderProviderConfigurationUtils class has package visibility. Can we change that to public to allow easy extension in such scenarios?
Comment From: jzheaux
@vishal423 there are no plans to make the utils class public as it continues to be quite a bit in flux. Perhaps you'd be interested in https://github.com/spring-projects/spring-security/issues/10309.
Comment From: ankit-donor360
@jgrandja , I feel the default
500msas connect/read timeout is too small in a low bandwidth usage scenario and we should update that to a more reasonable number.I also tried to write custom
JwtDecoderswith configurable timeouts, however, noted that the underlying usedJwtDecoderProviderConfigurationUtilsclass has package visibility. Can we change that topublicto allow easy extension in such scenarios?
@vishal423 Did you find the solution? I am facing same issue