Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quarkus 3.10 fails to start if some OIDC providers don't support UserInfo #40434

Closed
sberyozkin opened this issue May 3, 2024 Discussed in #40412 · 4 comments · Fixed by #40456
Closed

Quarkus 3.10 fails to start if some OIDC providers don't support UserInfo #40434

sberyozkin opened this issue May 3, 2024 Discussed in #40412 · 4 comments · Fixed by #40456
Labels
area/oidc kind/bug Something isn't working
Milestone

Comments

@sberyozkin
Copy link
Member

Discussed in #40412

Originally posted by markusdlugi May 2, 2024
Opening this as discussion since I don't know if this can actually be considered to be a bug. Just wanted to discuss this and raise awareness about the behavior 😄

With #39428 some behavior was introduced to automagically detect whether UserInfo is injected in the application or not. If that is the case, the user-info-required property will be enabled by Quarkus itself.

While this is a nice QOL improvement for most Quarkus users, this can cause trouble when there are multiple OIDC providers configured and some of them don't support UserInfo acquisition. For example, we have a corporate OIDC provider that is used for user auth and additionally use an AWS EKS OIDC provider for M2M use-cases. The latter one does not have a user-info endpoint.

In such a scenario, Quarkus will fail to start with the following exception:

UserInfo is required but the OpenID Provider UserInfo endpoint is not configured. Use 'quarkus.oidc.user-info-path' if the discovery is disabled.
 java.lang.RuntimeException: Failed to start quarkus
     at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
     at io.quarkus.runtime.Application.start(Application.java:101)
     at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:111)
     at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
     at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
     at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
     at io.quarkus.runner.GeneratedMain.main(Unknown Source)
     at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
     at java.base/java.lang.reflect.Method.invoke(Method.java:580)
     at io.quarkus.bootstrap.runner.QuarkusEntryPoint.doRun(QuarkusEntryPoint.java:62)
     at io.quarkus.bootstrap.runner.QuarkusEntryPoint.main(QuarkusEntryPoint.java:33)
 Caused by: io.smallrye.mutiny.CompositeException: Multiple exceptions caught:
     [Exception 0] io.quarkus.runtime.configuration.ConfigurationException: UserInfo is required but the OpenID Provider UserInfo endpoint is not configured. Use 'quarkus.oidc.user-info-path' if the discovery is disabled.
     [Exception 1] io.quarkus.oidc.OIDCException
     at io.smallrye.mutiny.operators.uni.UniOnFailureFlatMap$UniOnFailureFlatMapProcessor.performInnerSubscription(UniOnFailureFlatMap.java:94)
     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.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.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.onItem(UniOnItemOrFailureFlatMap.java:54)
     at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
     at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onItem(UniOperatorProcessor.java:47)
     at io.smallrye.mutiny.operators.uni.builders.UniCreateFromPublisher$PublisherSubscriber.onNext(UniCreateFromPublisher.java:70)
     at io.smallrye.mutiny.subscription.MultiSubscriberAdapter.onItem(MultiSubscriberAdapter.java:27)
     at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
     at io.smallrye.mutiny.subscription.SerializedSubscriber.onItem(SerializedSubscriber.java:74)
     at io.smallrye.mutiny.operators.multi.MultiRetryWhenOp$RetryWhenOperator.onItem(MultiRetryWhenOp.java:111)
     at io.smallrye.mutiny.subscription.MultiSubscriber.onNext(MultiSubscriber.java:61)
     at io.smallrye.mutiny.converters.uni.UniToMultiPublisher$UniToMultiSubscription.onItem(UniToMultiPublisher.java:94)
     at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
     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:279)
     at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:261)
     at io.vertx.core.impl.ContextInternal.lambda$runOnContext$0(ContextInternal.java:59)
     at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
     at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
     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:1583)
     Suppressed: io.quarkus.oidc.OIDCException
         at io.quarkus.oidc.runtime.OidcRecorder$5.apply(OidcRecorder.java:159)
         at io.quarkus.oidc.runtime.OidcRecorder$5.apply(OidcRecorder.java:141)
         at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
         at io.smallrye.mutiny.groups.UniOnFailure.lambda$recoverWithItem$8(UniOnFailure.java:190)
         at io.smallrye.mutiny.operators.uni.UniOnFailureFlatMap$UniOnFailureFlatMapProcessor.performInnerSubscription(UniOnFailureFlatMap.java:92)
         ... 39 more
     Caused by: io.quarkus.runtime.configuration.ConfigurationException: UserInfo is required but the OpenID Provider UserInfo endpoint is not configured. Use 'quarkus.oidc.user-info-path' if the discovery is disabled.
         at io.quarkus.oidc.runtime.OidcRecorder$11.apply(OidcRecorder.java:545)
         at io.quarkus.oidc.runtime.OidcRecorder$11.apply(OidcRecorder.java:519)
         at io.smallrye.context.impl.wrappers.SlowContextualBiFunction.apply(SlowContextualBiFunction.java:21)
         at io.smallrye.mutiny.operators.uni.UniOnItemOrFailureFlatMap$UniOnItemOrFailureFlatMapProcessor.performInnerSubscription(UniOnItemOrFailureFlatMap.java:86)
         ... 30 more
 Caused by: [CIRCULAR REFERENCE: io.quarkus.runtime.configuration.ConfigurationException: UserInfo is required but the OpenID Provider UserInfo endpoint is not configured. Use 'quarkus.oidc.user-info-path' if the discovery is disabled.]

Our configuration prior to Quarkus 3.10 looked like this:

quarkus:
  oidc:
    "https://oidc.eks.eu-central-1.amazonaws.com/id/ABCDEF123456":
      auth-server-url: "https://oidc.eks.eu-central-1.amazonaws.com/id/ABCDEF123456"
      token:
        forced-jwk-refresh-interval: 0S
        allow-jwt-introspection: false
        allow-opaque-token-introspection: false
        audience: sts.amazonaws.com
    auth-server-url: https://auth.acme.com/auth/oauth2/realms/root/realms/intranetb2x
    token:
      refresh-expired: true
      refresh-token-time-skew: 10M
    application-type: web-app
    client-id: ${OIDC_CLIENT_ID}
    credentials:
      secret: ${OIDC_CLIENT_SECRET}
    authentication:
      java-script-auto-redirect: false
      redirect-path: /app/ui
      user-info-required: true
      scopes: profile microprofile
    roles:
      source: userinfo
    token-cache:
      max-size: 1000
      time-to-live: 5M
      clean-up-timer-interval: 1M
    token-state-manager:
      split-tokens: true
    logout:
      path: /app/logout
      post-logout-path: /app/ui

The failure can be worked around by explicitly disabling user-info-required for the EKS tenant. Therefore, I'm not sure whether this is a bug actually. But it's a little nuisance since such a configuration wasn't required previously. You might argue that most users will rather have a single OIDC provider and so they are less likely to run into this problem, therefore this might still be worth it 😅 But maybe we could have some smartness to avoid the failure in this scenario?

Copy link

quarkus-bot bot commented May 3, 2024

/cc @pedroigor (oidc)

@quarkus-bot quarkus-bot bot added the area/oidc label May 3, 2024
@sberyozkin sberyozkin added the kind/bug Something isn't working label May 3, 2024
@sberyozkin
Copy link
Member Author

@michalvavrik Would you like me to look into it since I should've thought about this variation earlier ? Or do you you have a straightforward fix in mind ? The only question is how to pass the fact the injection point for UserInfo is available to OidcRecorder, using the runtime property or system property build item should do, as we don't want to analyze the injection points at runtime

@sberyozkin
Copy link
Member Author

Two of us can work in it, I can look into updating one of the integration tests for your PR if you decide to do it as the current test checking it was set at build time will need to be removed, let me know what you prefer

@michalvavrik
Copy link
Member

all-comments-placeholder

Roger that.

Would you like me to look into it since I should've thought about this variation earlier ?
Two of us can work in it, I can look into updating one of the integration tests for your PR if you decide to do it as the current test checking it was set at build time will need to be removed, let me know what you prefer

This is how I understood your comments - #40456. Please feel free to come with your own version / close it / adjust / whatever.

@quarkus-bot quarkus-bot bot added this to the 3.11 - main milestone May 4, 2024
@gsmet gsmet modified the milestones: 3.11 - main, 3.10.1 May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/oidc kind/bug Something isn't working
Projects
None yet
3 participants