Closed
Description
Describe the bug
We're using OIDC extension with storing all tokens (id, access and refresh token) in the q_session cookie. In the application, we require the userinfo also, so we set quarkus.oidc.authentication.user-info-required=true
. When the access token expires and the userinfo is not cached (e.g. because of a server restart), we get a 401 as response.
Expected behavior
The access token is refreshed before the userinfo is retrieved and we are successfully authenticated
Actual behavior
The user info endpoint is called before the access token is refreshed and the exception of the call does not trigger the token to refresh, resulting in a 401 access denied
How to Reproduce?
- Create an oidc application with following parameters:
quarkus.oidc.auth-server-url=https://oidc-server.com quarkus.oidc.client-id=MY_CLIENT quarkus.oidc.application-type=web-app quarkus.oidc.authentication.user-info-required=true
- Start the application and log in.
- Restart the application.
- Reload the page
Output of uname -a
or ver
No response
Output of java -version
openjdk version "17.0.3" 2022-04-19 LTS
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.15.2
Build tool (ie. output of mvnw --version
or gradlew --version
)
Apache Maven 3.8.6
Additional information
Log from the 401 response:
2023-01-05 17:10:02,561 DEBUG [io.qua.oid.run.DefaultTenantConfigResolver] (vert.x-eventloop-thread-2) Registered TenantResolver has not provided the configuration for tenant 'Default', using the default tenant
2023-01-05 17:10:02,563 DEBUG [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-2) Session cookie is present, starting the reauthentication
2023-01-05 17:10:02,564 DEBUG [io.qua.oid.run.DefaultTenantConfigResolver] (vert.x-eventloop-thread-2) Registered TenantResolver has not provided the configuration for tenant 'Default', using the default tenant
2023-01-05 17:10:02,566 DEBUG [io.qua.oid.run.OidcIdentityProvider] (vert.x-eventloop-thread-2) Starting creating SecurityIdentity
2023-01-05 17:10:02,567 DEBUG [io.qua.oid.run.DefaultTenantConfigResolver] (vert.x-eventloop-thread-2) Registered TenantResolver has not provided the configuration for tenant 'Default', using the default tenant
2023-01-05 17:10:02,568 DEBUG [io.qua.oid.run.OidcIdentityProvider] (vert.x-eventloop-thread-2) Requesting UserInfo
2023-01-05 17:10:02,569 DEBUG [io.qua.oid.run.OidcProviderClient] (vert.x-eventloop-thread-2) Get UserInfo on: https://***********/oauth/userinfo auth: Bearer *******************
2023-01-05 17:10:02,637 DEBUG [io.qua.oid.run.OidcProviderClient] (vert.x-eventloop-thread-2) Request has failed: status: 401, error message: null
2023-01-05 17:10:02,647 ERROR [io.qua.oid.run.CodeAuthenticationMechanism] (vert.x-eventloop-thread-2) ID token verification failure: io.quarkus.oidc.OIDCException
2023-01-05 17:10:02,648 DEBUG [io.qua.ver.htt.run.sec.HttpSecurityRecorder] (vert.x-eventloop-thread-2) Authentication has failed, returning HTTP status 401
2023-01-05 17:10:02,650 DEBUG [io.ver.ext.web.RoutingContext] (vert.x-eventloop-thread-2) RoutingContext failure (500): io.quarkus.security.AuthenticationCompletionException
at io.quarkus.oidc.runtime.CodeAuthenticationMechanism$5$1.apply(CodeAuthenticationMechanism.java:290)
at io.quarkus.oidc.runtime.CodeAuthenticationMechanism$5$1.apply(CodeAuthenticationMechanism.java:270)
at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
at io.smallrye.mutiny.operators.uni.UniOnFailureFlatMap$UniOnFailureFlatMapProcessor.performInnerSubscription(UniOnFailureFlatMap.java:92)
at io.smallrye.mutiny.operators.uni.UniOnFailureFlatMap$UniOnFailureFlatMapProcessor.dispatch(UniOnFailureFlatMap.java:83)
at io.smallrye.mutiny.operators.uni.UniOnFailureFlatMap$UniOnFailureFlatMapProcessor.onFailure(UniOnFailureFlatMap.java:60)
at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.onFailure(UniOnItemOrFailureFlatMap.java:67)
at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.onFailure(UniOnItemOrFailureFlatMap.java:67)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownFailure$KnownFailureSubscription.forward(UniCreateFromKnownFailure.java:38)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownFailure$KnownFailureSubscription.access$100(UniCreateFromKnownFailure.java:26)
at io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownFailure.subscribe(UniCreateFromKnownFailure.java:23)
at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.performInnerSubscription(UniOnItemOrFailureFlatMap.java:99)
at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.onFailure(UniOnItemOrFailureFlatMap.java:65)
at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:40)
at io.smallrye.mutiny.vertx.AsyncResultUni.lambda$subscribe$1(AsyncResultUni.java:35)
at io.smallrye.mutiny.vertx.DelegatingHandler.handle(DelegatingHandler.java:25)
at io.vertx.ext.web.client.impl.HttpContext.handleDispatchResponse(HttpContext.java:397)
at io.vertx.ext.web.client.impl.HttpContext.execute(HttpContext.java:384)
at io.vertx.ext.web.client.impl.HttpContext.next(HttpContext.java:362)
at io.vertx.ext.web.client.impl.HttpContext.fire(HttpContext.java:329)
at io.vertx.ext.web.client.impl.HttpContext.dispatchResponse(HttpContext.java:291)
at io.vertx.ext.web.client.impl.HttpContext.lambda$null$7(HttpContext.java:507)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:264)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:246)
at io.vertx.core.impl.EventLoopContext.lambda$runOnContext$0(EventLoopContext.java:43)
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:566)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: io.quarkus.oidc.OIDCException
at io.quarkus.oidc.runtime.OidcProviderClient.responseException(OidcProviderClient.java:204)
at io.quarkus.oidc.runtime.OidcProviderClient.getString(OidcProviderClient.java:197)
at io.quarkus.oidc.runtime.OidcProviderClient.getUserInfo(OidcProviderClient.java:176)
at io.quarkus.oidc.runtime.OidcProviderClient.lambda$getUserInfo$1(OidcProviderClient.java:81)
at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:36)
... 19 more
2023-01-05 17:10:02,657 DEBUG [io.qua.mic.run.bin.ver.VertxHttpServerMetrics] (vert.x-eventloop-thread-2) requestRouted null HttpRequestMetric [initialPath=/, currentRoutePath=null, templatePath=null, request=io.vertx.core.http.impl.Http1xServerRequest@6af3714e]
2023-01-05 17:10:02,659 DEBUG [io.qua.mic.run.bin.ver.VertxHttpServerMetrics] (vert.x-eventloop-thread-2) requestRouted null HttpRequestMetric [initialPath=/, currentRoutePath=null, templatePath=null, request=io.vertx.core.http.impl.Http1xServerRequest@6af3714e]
2023-01-05 17:10:02,660 DEBUG [io.qua.mic.run.bin.ver.VertxHttpServerMetrics] (vert.x-eventloop-thread-2) responseEnd io.vertx.core.http.impl.Http1xServerResponse@3dc5fcac, HttpRequestMetric [initialPath=/, currentRoutePath=null, templatePath=null, request=io.vertx.core.http.impl.Http1xServerRequest@6af3714e]
2023-01-05 17:10:02,662 DEBUG [io.qua.ver.htt.run.ForwardedParser] (vert.x-eventloop-thread-2) Recalculated absoluteURI to http://localhost:8080/
2023-01-05 17:10:02,664 INFO [io.qua.htt.access-log] (vert.x-eventloop-thread-2) 127.0.0.1 - - 05/Jan/2023:17:10:02 +0100 "GET / HTTP/1.1" 401 -