Quarkus fails to report a correct exception when conflicting authentication mechanisms are used (was Quarkus: can't verify Auth0 token)
See original GitHub issueDescribe 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:
- Create free Auth0 tenant.
- Create new API application with RSA256 signing algorithm.
- Add
http://localhost:8080/
to allowed callback URLs for the API application. - Rewrite redacted values from configuration with the corresponding API application properties.
- 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:
- Created 2 years ago
- Comments:9 (5 by maintainers)
Top 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 >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Alright, thanks for your help.
When I add
quarkus-smallrye-jwt
tointegration-tests/oidc
which already has thequarkus-oidc
dependency then I see:which is expected. It is the
main
branch. However, adding both dependencies toquarkus-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