spring-security: Question: Set the timeouts used when retrieving Keys for JWT validation

This is a question: I am trying out the v5 oauth changes, eventually hoping to try the open id client support. I’m running the boot oauth2login same in the 5.0.0 M3 release. I have added a new client to connect to an Azure Active Directory account I have. It is working… I can see the token coming back. But it fails when validating the token.

This is the call stack I see in the system.out for the process running the sample

org.springframework.security.jwt.JwtException: An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: connect timed out
	at org.springframework.security.jwt.nimbus.NimbusJwtDecoderJwkSupport.decode(NimbusJwtDecoderJwkSupport.java:108) ~[spring-security-jwt-jose-5.0.0.M3.jar!/:na]
	at org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProvider.authenticate(AuthorizationCodeAuthenticationProvider.java:119) ~[spring-security-oauth2-client-5.0.0.M3.jar!/:na]
	at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.0.0.M3.jar!/:na]
	at org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProcessingFilter.attemptAuthentication(AuthorizationCodeAuthenticationProcessingFilter.java:154) ~[spring-security-oauth2-client-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.oauth2.client.authentication.AuthorizationCodeRequestRedirectFilter.doFilterInternal(AuthorizationCodeRequestRedirectFilter.java:100) ~[spring-security-oauth2-client-5.0.0.M3.jar!/:na]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-5.0.0.M3.jar!/:na]
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:350) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:265) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:199) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.0.RC2.jar!/:5.0.0.RC2]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar!/:8.5.16]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]
Caused by: com.nimbusds.jose.RemoteKeySourceException: Couldn't retrieve remote JWK set: connect timed out
	at com.nimbusds.jose.jwk.source.RemoteJWKSet.updateJWKSetFromURL(RemoteJWKSet.java:141) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at com.nimbusds.jose.jwk.source.RemoteJWKSet.get(RemoteJWKSet.java:219) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at com.nimbusds.jose.proc.JWSVerificationKeySelector.selectJWSKeys(JWSVerificationKeySelector.java:129) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:323) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:284) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at org.springframework.security.jwt.nimbus.NimbusJwtDecoderJwkSupport.decode(NimbusJwtDecoderJwkSupport.java:92) ~[spring-security-jwt-jose-5.0.0.M3.jar!/:na]
	... 59 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_111]
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[na:1.8.0_111]
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_111]
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_111]
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_111]
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_111]
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_111]
	at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_111]
	at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668) ~[na:1.8.0_111]
	at sun.net.NetworkClient.doConnect(NetworkClient.java:175) ~[na:1.8.0_111]
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) ~[na:1.8.0_111]
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) ~[na:1.8.0_111]
	at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264) ~[na:1.8.0_111]
	at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:367) ~[na:1.8.0_111]
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191) ~[na:1.8.0_111]
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1138) ~[na:1.8.0_111]
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1032) ~[na:1.8.0_111]
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177) ~[na:1.8.0_111]
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546) ~[na:1.8.0_111]
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474) ~[na:1.8.0_111]
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) ~[na:1.8.0_111]
	at com.nimbusds.jose.util.DefaultResourceRetriever.retrieveResource(DefaultResourceRetriever.java:97) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	at com.nimbusds.jose.jwk.source.RemoteJWKSet.updateJWKSetFromURL(RemoteJWKSet.java:139) ~[nimbus-jose-jwt-4.34.1.jar!/:4.34.1]
	... 64 common frames omitted

From what I have pieced together, the framework is attempting to retrieve the keys from the jwk-set-uri value and not getting the value in time. When I debug this, the default values of 250 ms is used for both the connect and read timeout for the nimbus classes involved.

When I load the same URL using my browser, it completes. To the URL is valid. However, from where I’m running, it usually takes >400 ms to load. I’m happy to says it’s caused by my network, but I’m not going to be able to change this.

Is there any chance that those timeouts will be configurable? I feel like if I can just increase those timeouts, this will work just fine.

Thanks for any help. Ed

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 28 (12 by maintainers)

Most upvoted comments

@sshogunn The default connection timeout needs to be increased in DefaultResourceRetriever which is associated in RemoteJWKSet. You will need to address this with the Microsoft team as they are not using Spring Security and instead using Nimbus library directly.

@vipinsaini434 I come across the same problem and got a better solution:

  ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
  JWKSource jwkSource = null;
  // connection timeout and read timeout can be configured here
  ResourceRetriever jwkRetriever = new DefaultResourceRetriever(100000, 100000);
  jwkSource = new RemoteJWKSet(new URL(jsonWebKeyFileURL), jwkRetriever);
  JWSAlgorithm jwsAlgorithm = JWSAlgorithm.RS256;
  JWSKeySelector keySelector = new JWSVerificationKeySelector(jwsAlgorithm, jwkSource);
  jwtProcessor.setJWSKeySelector(keySelector);
  JWTClaimsSet claimsSet = jwtProcessor.process(token, null);