question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Quarkus fails to report a correct exception when conflicting authentication mechanisms are used (was Quarkus: can't verify Auth0 token)

See original GitHub issue

Describe the bug

I have the following OIDC configuration:

quarkus.oidc.auth-server-url=https://cognio.eu.auth0.com
quarkus.oidc.client-id=<redacted>
quarkus.oidc.credentials.secret=<redacted>
quarkus.oidc.token.audience=<redacted>
quarkus.oidc.authentication.scopes=openid,profile,email

quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated

While trying to access any endpoint with a valid access token I receive following response:

HTTP/1.1 401 Unauthorized
www-authenticate: Bearer
content-length: 0

If logging level is set to DEBUG the following stack trace is printed:

2021-07-28 14:47:08,037 DEBUG [io.sma.jwt.aut.principal] (vert.x-eventloop-thread-7) SRJWT08019: AuthContextInfo is: JWTAuthContextInfo{publicVerificationKey=null, secretVerificationKey=null, privateDecryptionKey=null, secretDecryptionKey=null, issuedBy='null', expGracePeriodSecs=60, maxTimeToLiveSecs=null, publicKeyLocation='null', publicKeyContent='null', decryptionKeyLocation='null', decryptionKeyContent='null', jwksRefreshInterval=60, tokenHeader='Authorization', tokenCookie='null', alwaysCheckAuthorization=false, tokenKeyId='null', tokenDecryptionKeyId='null', tokenSchemes=[Bearer], requireNamedPrincipal=true, defaultSubClaim='null', subPath='null', defaultGroupsClaim='null', groupsPath='null', signatureAlgorithm=RS256, keyEncryptionAlgorithm=RSA_OAEP, keyFormat=ANY, expectedAudience=null, groupsSeparator=' ', relaxVerificationKeyValidation=true, verifyCertificateThumbprint=false}
2021-07-28 14:47:08,040 DEBUG [io.sma.jwt.aut.principal] (vert.x-eventloop-thread-7) SRJWT08005: Verification key is unresolvable
2021-07-28 14:47:08,040 DEBUG [io.qua.sma.jwt.run.aut.MpJwtValidator] (vert.x-eventloop-thread-7) Authentication failed: io.smallrye.jwt.auth.principal.ParseException: SRJWT07000: Failed to verify a token
	at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parseClaims(DefaultJWTTokenParser.java:164)
	at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parse(DefaultJWTTokenParser.java:56)
	at io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipalFactory.parse(DefaultJWTCallerPrincipalFactory.java:31)
	at io.smallrye.jwt.auth.principal.DefaultJWTParser.parse(DefaultJWTParser.java:60)
	at io.smallrye.jwt.auth.principal.DefaultJWTParser_Subclass.parse$$superforward1(DefaultJWTParser_Subclass.zig:517)
	at io.smallrye.jwt.auth.principal.DefaultJWTParser_Subclass$$function$$6.apply(DefaultJWTParser_Subclass$$function$$6.zig:33)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:51)
	at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)
	at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
	at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
	at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
	at io.smallrye.jwt.auth.principal.DefaultJWTParser_Subclass.parse(DefaultJWTParser_Subclass.zig:1180)
	at io.smallrye.jwt.auth.principal.DefaultJWTParser_ClientProxy.parse(DefaultJWTParser_ClientProxy.zig:298)
	at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator$1.accept(MpJwtValidator.java:53)
	at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator$1.accept(MpJwtValidator.java:49)
	at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
	at io.smallrye.mutiny.operators.uni.builders.UniCreateWithEmitter.subscribe(UniCreateWithEmitter.java:22)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.operators.uni.UniMemoizeOp.subscribe(UniMemoizeOp.java:76)
	at io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)
	at io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:50)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:104)
	at io.quarkus.vertx.http.runtime.security.HttpSecurityRecorder$2.handle(HttpSecurityRecorder.java:51)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1127)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:151)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:88)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$3.handle(VertxHttpHotReplacementSetup.java:77)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:124)
	at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	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:829)
Caused by: org.jose4j.lang.UnresolvableKeyException: SRJWT07003: Failed to load a key from null
	at io.smallrye.jwt.auth.principal.AbstractKeyLocationResolver.reportLoadKeyException(AbstractKeyLocationResolver.java:180)
	at io.smallrye.jwt.auth.principal.KeyLocationResolver.<init>(KeyLocationResolver.java:47)
	at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.getVerificationKeyResolver(DefaultJWTTokenParser.java:236)
	at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parseClaims(DefaultJWTTokenParser.java:99)
	... 42 more
Caused by: java.lang.NullPointerException
	at io.smallrye.jwt.util.ResourceUtils.getResourceStream(ResourceUtils.java:68)
	at io.smallrye.jwt.util.ResourceUtils.readResource(ResourceUtils.java:44)
	at io.smallrye.jwt.auth.principal.AbstractKeyLocationResolver.readKeyContent(AbstractKeyLocationResolver.java:131)
	at io.smallrye.jwt.auth.principal.KeyLocationResolver.initializeKeyContent(KeyLocationResolver.java:95)
	at io.smallrye.jwt.auth.principal.KeyLocationResolver.<init>(KeyLocationResolver.java:45)
	... 44 more

Expected behavior

Quarkus should successfully verify token and give access to endpoint.

Actual behavior

Quarkus throws exception.

How to Reproduce?

Steps to reproduce:

  1. Create free Auth0 tenant.
  2. Create new API application with RSA256 signing algorithm.
  3. Add http://localhost:8080/ to allowed callback URLs for the API application.
  4. Rewrite redacted values from configuration with the corresponding API application properties.
  5. Start service.

Output of uname -a or ver

No response

Output of java -version

11.0.12

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.0.3.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)

Additional information

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
cogniocodecommented, Jul 28, 2021

Alright, thanks for your help.

0reactions
sberyozkincommented, Jul 28, 2021

When I add quarkus-smallrye-jwt to integration-tests/oidc which already has the quarkus-oidc dependency then I see:

2021-07-28 14:17:10,189 ERROR [io.ver.ext.web.RoutingContext] (vert.x-eventloop-thread-1) Unhandled exception in router: java.lang.RuntimeException: Multiple mechanisms present that use the same credential transport HttpCredentialTransport{transportType=AUTHORIZATION, typeTarget='bearer', authenticationScheme='Bearer'}. Mechanisms are io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism@2ad126bc and io.quarkus.oidc.runtime.OidcAuthenticationMechanism@6120bcef

which is expected. It is the main branch. However, adding both dependencies to quarkus-quickstart/security-openid-connect-quickstart makes no difference, sending a bogus token returns 401 as expected, no exception as shown in the description is thrown so something is inconsistent here

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using JWT RBAC - Quarkus
This guide explains how your Quarkus application can utilize SmallRye JWT to verify JSON Web Tokens, represent them as MicroProfile JWT ...
Read more >
Quarkus Security overview
Quarkus Security is a framework that provides the architecture, multiple authentication and authorization mechanisms, and other tools for you to build ...
Read more >
OpenID Connect (OIDC) authorization code flow mechanism
The Authorization Code Flow mechanism authenticates users of your web application by redirecting them to an OIDC provider, such as Keycloak, to log...
Read more >
Using OpenID Connect (OIDC) to Protect Service Applications ...
The Quarkus service retrieves verification keys from the OpenID Connect provider. The verification keys are used to verify the bearer access token signatures....
Read more >
Security Tips and Tricks - Quarkus
Basic authentication mechanism has the highest priority of 2000 ... returned if no credentials are provided and if JWT and Authorization Code mechanisms...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found