Skip to content

Question: Set the timeouts used when retrieving Keys for JWT validation #4474

@hildo

Description

@hildo

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

Metadata

Metadata

Assignees

Labels

in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions