Closed sivaraman-27 closed 1 year ago
Update 1:
I found the exception was thrown from 'UrlJwkProvider.java'. Below is the code
private Map<String, Object> getJwks() throws SigningKeyNotFoundException {
try {
final URLConnection c = (proxy == null) ? this.url.openConnection() : this.url.openConnection(proxy);
if (connectTimeout != null) {
c.setConnectTimeout(connectTimeout);
}
if (readTimeout != null) {
c.setReadTimeout(readTimeout);
}
for (Map.Entry<String, String> entry : headers.entrySet()) {
c.setRequestProperty(entry.getKey(), entry.getValue());
}
try (InputStream inputStream = c.getInputStream()) {
return reader.readValue(inputStream);
}
} catch (IOException e) {
throw new NetworkException("Cannot obtain jwks from url " + url.toString(), e);
}
}
For new UrlJwkProvider, I'm only passing "Microsoft URL" alone, rest of them are null
public UrlJwkProvider(URL url) {
this(url, null, null, null, null);
}
Hi, @jimmyjames. Can you give any reasons for the above error?
@sivaraman-27 Azure AD and some other IDPs use a different URL path structure for the JWKS endpoint. With those, you will have to specify the URL path explicitly. For my Azure AD IDP the URL is https://login.microsoftonline.com/<clientId>/discovery/v2.0/keys
so I used this code:
provider = new UrlJwkProvider(new URL("https://login.microsoftonline.com/<clientId>/discovery/v2.0/keys"));
See https://github.com/auth0/jwks-rsa-java/issues/112 for more info.
I read source code of jwks-rsa-java and I noticed the same issue of this.
/.well-known/
paths are specified in internet standard and you can see on the following page.
https://www.iana.org/assignments/well-known-uris/well-known-uris.xhtml
/.well-known/openid-configuration
is an internet standard based on OpenID Connect specs, but /.well-known/jwks.json
is not allowed as a standard URL.
It requires extra internet access, but I beleave getting JWK's location form /.well-known/openid-configuration
is the politest way to get JWKs.
@axis80 I tested on AzureAD and I got the following OpenID configuration path
https://login.microsoftonline.com/<tenantID>/.well-known/openid-configuration
And it returns the following path.
https://login.microsoftonline.com/common/discovery/keys
I couldn't access the path you mentioned.
Thanks everyone for the help and ideas!
I'm trying to understand the issue at hand here, if I try the following it works as expected:
String url = "https://login.microsoftonline.com/common/discovery/v2.0/keys";
UrlJwkProvider provider = new UrlJwkProvider(new URI(url).normalize().toURL());
System.out.println(provider.get("{SOME-KID}"));
@axis80 is correct that we don't currently traverse the discovery URL as discussed in #112, but not sure if that's related to this specific issue or not.
If there's an example that reproduces an issue let us know, thanks!
Potentially related, #165 may help in this case by at least throwing a more specific exception.
While UrlJwkProvider
works for me, I ran into a similar issue when using JwkProviderBuilder
public JwkProviderBuilder(String domain)
's doc says
It can be a url link 'https://samples.auth0.com' or just a domain 'samples.auth0.com'. If the protocol (http or https) is not provided then https is used by default. The default jwks path "/.well-known/jwks.json" is appended to the given string domain.
For example, when the domain is "samples.auth0.com" the jwks url that will be used is "https://samples.auth0.com/.well-known/jwks.json"
I agree with @shibukawa 's comment because I am using Keycloak and its default jwks_uri (which can be got from its ".well-known/openid-configuration") is like http://localhost:8080/auth/realms/master/protocol/openid-connect/certs
which has nothing to do with "/.well-known/jwks.json".
Here is the backtrace of JwkProviderBuilder("http://0.0.0.0:18080/realms/real-world/protocol/openid-connect/certs")
2023-03-22 10:12:49.487 [eventLoopGroupProxy-4-3] TRACE io.ktor.server.auth.Authentication - Trying to authenticate /hello with keycloakJWT
2023-03-22 10:12:49.562 [eventLoopGroupProxy-4-3] TRACE io.ktor.auth.jwt - Failed to get JWK
com.auth0.jwk.SigningKeyNotFoundException: Failed to get key with kid l1YB4RV4wFs88KmbNOuXACmN40cgQcauRPhQ7rOyrkQ
at com.auth0.jwk.GuavaCachedJwkProvider.get(GuavaCachedJwkProvider.java:70)
at io.ktor.server.auth.jwt.JWTUtilsKt.getVerifier(JWTUtils.kt:55)
at io.ktor.server.auth.jwt.JWTAuthenticationProvider$Config$verifier$4.invoke(JWTAuth.kt:250)
at io.ktor.server.auth.jwt.JWTAuthenticationProvider$Config$verifier$4.invoke(JWTAuth.kt:250)
at io.ktor.server.auth.jwt.JWTAuthenticationProvider.onAuthenticate(JWTAuth.kt:160)
at io.ktor.server.auth.AuthenticationInterceptorsKt$AuthenticationInterceptors$2$1.invokeSuspend(AuthenticationInterceptors.kt:102)
at io.ktor.server.auth.AuthenticationInterceptorsKt$AuthenticationInterceptors$2$1.invoke(AuthenticationInterceptors.kt)
at io.ktor.server.auth.AuthenticationInterceptorsKt$AuthenticationInterceptors$2$1.invoke(AuthenticationInterceptors.kt)
at io.ktor.server.auth.AuthenticationHook$install$1.invokeSuspend(AuthenticationInterceptors.kt:25)
at io.ktor.server.auth.AuthenticationHook$install$1.invoke(AuthenticationInterceptors.kt)
at io.ktor.server.auth.AuthenticationHook$install$1.invoke(AuthenticationInterceptors.kt)
at io.ktor.server.application.ApplicationPluginKt$addAllInterceptors$1$1$1.invokeSuspend(ApplicationPlugin.kt:167)
at io.ktor.server.application.ApplicationPluginKt$addAllInterceptors$1$1$1.invoke(ApplicationPlugin.kt)
at io.ktor.server.application.ApplicationPluginKt$addAllInterceptors$1$1$1.invoke(ApplicationPlugin.kt)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:120)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:78)
at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:98)
at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.server.routing.Routing$executeResult$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
at io.ktor.server.routing.Routing.executeResult(Routing.kt:190)
at io.ktor.server.routing.Routing.interceptor(Routing.kt:64)
at io.ktor.server.routing.Routing$Plugin$install$1.invokeSuspend(Routing.kt:140)
at io.ktor.server.routing.Routing$Plugin$install$1.invoke(Routing.kt)
at io.ktor.server.routing.Routing$Plugin$install$1.invoke(Routing.kt)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:120)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:78)
at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invokeSuspend(BaseApplicationEngine.kt:123)
at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invoke(BaseApplicationEngine.kt)
at io.ktor.server.engine.BaseApplicationEngineKt$installDefaultTransformationChecker$1.invoke(BaseApplicationEngine.kt)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:120)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:78)
at io.ktor.server.application.hooks.CallFailed$install$1$1.invokeSuspend(CommonHooks.kt:43)
at io.ktor.server.application.hooks.CallFailed$install$1$1.invoke(CommonHooks.kt)
at io.ktor.server.application.hooks.CallFailed$install$1$1.invoke(CommonHooks.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
at io.ktor.server.application.hooks.CallFailed$install$1.invokeSuspend(CommonHooks.kt:42)
at io.ktor.server.application.hooks.CallFailed$install$1.invoke(CommonHooks.kt)
at io.ktor.server.application.hooks.CallFailed$install$1.invoke(CommonHooks.kt)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:120)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:78)
at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:98)
at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invokeSuspend(DefaultEnginePipeline.kt:118)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invoke(DefaultEnginePipeline.kt)
at io.ktor.server.engine.DefaultEnginePipelineKt$defaultEnginePipeline$1.invoke(DefaultEnginePipeline.kt)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:120)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:78)
at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:98)
at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1$invokeSuspend$$inlined$execute$1.invokeSuspend(Pipeline.kt:478)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1$invokeSuspend$$inlined$execute$1.invoke(Pipeline.kt)
at io.ktor.util.debug.ContextUtilsKt.initContextInDebugMode(ContextUtils.kt:17)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.invokeSuspend(NettyApplicationCallHandler.kt:119)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.invoke(NettyApplicationCallHandler.kt)
at io.ktor.server.netty.NettyApplicationCallHandler$handleRequest$1.invoke(NettyApplicationCallHandler.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:112)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
at io.ktor.server.netty.NettyApplicationCallHandler.handleRequest(NettyApplicationCallHandler.kt:37)
at io.ktor.server.netty.NettyApplicationCallHandler.channelRead(NettyApplicationCallHandler.kt:29)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:61)
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:425)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.ktor.server.netty.EventLoopGroupProxy$Companion.create$lambda$1$lambda$0(NettyApplicationEngine.kt:291)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.util.concurrent.ExecutionException: com.auth0.jwk.NetworkException: Cannot obtain jwks from url http://0.0.0.0:18080/realms/real-world/protocol/openid-connect/certs/.well-known/jwks.json
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:566)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:527)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:104)
at com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(Uninterruptibles.java:240)
at com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2313)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2279)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2155)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2045)
at com.google.common.cache.LocalCache.get(LocalCache.java:3951)
at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4848)
at com.auth0.jwk.GuavaCachedJwkProvider.get(GuavaCachedJwkProvider.java:63)
... 82 common frames omitted
Caused by: com.auth0.jwk.NetworkException: Cannot obtain jwks from url http://0.0.0.0:18080/realms/real-world/protocol/openid-connect/certs/.well-known/jwks.json
at com.auth0.jwk.UrlJwkProvider.getJwks(UrlJwkProvider.java:139)
at com.auth0.jwk.UrlJwkProvider.getAll(UrlJwkProvider.java:145)
at com.auth0.jwk.UrlJwkProvider.get(UrlJwkProvider.java:163)
at com.auth0.jwk.RateLimitedJwkProvider.get(RateLimitedJwkProvider.java:28)
at com.auth0.jwk.GuavaCachedJwkProvider$1.call(GuavaCachedJwkProvider.java:66)
at com.auth0.jwk.GuavaCachedJwkProvider$1.call(GuavaCachedJwkProvider.java:63)
at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4853)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3529)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2278)
... 87 common frames omitted
Caused by: java.io.FileNotFoundException: http://0.0.0.0:18080/realms/real-world/protocol/openid-connect/certs/.well-known/jwks.json
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1993)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1589)
at com.auth0.jwk.UrlJwkProvider.getJwks(UrlJwkProvider.java:135)
... 95 common frames omitted
Hello, I'm encountering the issue "com.auth0.jwk.NetworkException: Cannot obtain jwks from url"
I'm trying to get the jwks from microsoft. But encountering the below issue
What was the expected behavior?
Successfully obtain jwks from the specified url
Reproduction
--
Environment