smallrye / smallrye-jwt Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
The io.smallrye.jwt.auth.principal.KeyLocationResolver.tryAsJWKx(String)
does not compare the kid
argument to the kid
entry on the JWK(S) object(s) fetched from mp.jwt.verify.publickey.location
.
For example, "file:C:\opt\jenkins\workspace\thorntail-pull-request-windows\testsuite\testsuite-microprofile-jwt/src/test/resources/keys/public-key.pem". The code should simply strip "file:" off as opposed to depending on URI.getSchemeSpecificPart()
in this case.
Hello Guys,
Do you know how to tell smallrye-jwt to use claim 'cognito:groups' as standard claim 'groups'?
Thanks a lot
Right now Thorntail and Quarkus have some CDI code which ideally should be located in smallrye-jwt in the form of CDIUtils
and may be AbstractExtension
referring to these CDIUtils
for Thorntail (and may be WildFly) CDI extension code, as well as any Quarkus code integrating smallrye-jwt be able to reuse the same code.
The scope claim, if present, will have the value such as a b c
as opposed to the expectation it would be an array. So if the mapping of scope
to groups
is needed then it won't work. A simple check that if it is a scope
then extract the roles from a string should do
I followed the instructions for AWS ALB OIDC authentication and configured Quarkus/SmallRye to read in the JWT from an HTTP header in the MP application.properties file:
#mp.jwt.verify.publickey.location=https://public-keys.auth.elb.us-west-1.amazonaws.com/some-uuid
mp.jwt.verify.publickey.location=META-INF/aws-jwt.pem
mp.jwt.verify.issuer=https://someorg.okta.com
smallrye.jwt.token.header=X-Amzn-Oidc-Data
quarkus.smallrye-jwt.auth-mechanism=MP-JWT
quarkus.smallrye-jwt.enabled=true
For whatever reason AWS resigns the JWT with their own key and they use Elilptic Curve based encryption and not RSA. When SmallRye tries to parse the PEM file remotely or locally it only tries to decode the PEM file as an RSA public key and fails.
Hello and thank you for your work.
I've introduced smallrye-jwt into my application and faced an SSL issue when the first request hit the secured endpoint.
So I'm guessing fetching JWKS from a remote location is lazy. Fine.
Is this put in a cache though ? I'm really concerned about this, since it could really slow down the incoming traffic dramatically, or even fail if JWKS endpoint is down for a moment.
I tried to look here but I'm not 100% sure.
Could you please confirm and close this issue/question if you have a few minutes? That'd be really helpful.
Thank you.
Is there any potential for this library to incorporate a CDI extension and perhaps an implementation of HttpAuthenticationMechanism
, falling back to the JAX-RS filter if no runtime is available? Using JSR-375 seems like a natural fit for an implementation of MP-JWT (knowing that the API does not use JSR-375).
As mentioned here :
eclipse/microprofile-jwt-auth#126
there are good reasons to have the token in the payload or in another HTTP header (like an httpOnly cookie).
At the moment 'KeyLocationResolver' loads a public key from the external resource on every request. This can be mostly optimized which will need to be done anyway (have a local volatile PublicKey property should do it for PEM or single JWK files).
But if it is a JWK set (which may contain N entries) then the problem is that the incoming 'kid' property can vary in theory so we can't settle on the single public key so iterating over the set every time can be expensive. In reality though it would be better and typically expected to have the same 'kid' - which would be managed at the key rotation point ex in the OIDC server. Expecting that every client may have used a different private key to sign is not really realistic from the security POV and as such the floating selection of keys from the JWK set can and should be optionally restricted to the specific 'kid' - and this will let it optimize the PublicKey creation as well.
Furthermore, with a new proiperty for specifying the key store format (PEM file, JKS store (in the future), JWK, JWKSet) the key selection can be further optimized.
It is related to #82 (we would not be able to do the above if the control of the JWK selection would stay inside Jose4J) so I'll fix both issues with a single PR
The certificates such as these ones should be supported
DEBUG [io.qu.sm.jw.ru.au.JwtIdentityManager]] (executor-thread-1) failed, [email protected], credential=io.quarkus.smallrye.jwt.runtime.auth.JWTCredential@7619667a: org.wildfly.security.auth.server.RealmUnavailableException: Failed to verify token
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator.validateClaimsSet(MpJwtValidator.java:44)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator.validate(MpJwtValidator.java:35)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator_ClientProxy.validate(Unknown Source)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.validateToken(TokenSecurityRealm.java:207)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.getClaims(TokenSecurityRealm.java:195)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.exists(TokenSecurityRealm.java:157)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.getEvidenceVerifySupport(TokenSecurityRealm.java:186)
at org.wildfly.security.auth.server.ServerAuthenticationContext$UnassignedState.verifyEvidence(ServerAuthenticationContext.java:1659)
at org.wildfly.security.auth.server.ServerAuthenticationContext$InactiveState.verifyEvidence(ServerAuthenticationContext.java:1391)
at org.wildfly.security.auth.server.ServerAuthenticationContext.verifyEvidence(ServerAuthenticationContext.java:759)
at org.wildfly.security.auth.server.SecurityDomain.authenticate(SecurityDomain.java:309)
at org.wildfly.security.auth.server.SecurityDomain.authenticate(SecurityDomain.java:270)
at io.quarkus.smallrye.jwt.runtime.auth.JwtIdentityManager.verify(JwtIdentityManager.java:36)
at io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism.authenticate(JWTAuthMechanism.java:53)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:245)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:268)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:231)
at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:125)
at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:99)
at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:92)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PathHandler.handleRequest(PathHandler.java:91)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.quarkus.undertow.runtime.UndertowDeploymentTemplate$8$1$1.call(UndertowDeploymentTemplate.java:482)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:197)
at io.undertow.server.handlers.HttpContinueReadHandler.handleRequest(HttpContinueReadHandler.java:65)
at io.quarkus.undertow.runtime.UndertowDeploymentTemplate$1.handleRequest(UndertowDeploymentTemplate.java:90)
at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup.handleHotDeploymentRequest(UndertowHotReplacementSetup.java:77)
at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup$1$1.handleRequest(UndertowHotReplacementSetup.java:56)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:243)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1395)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:32)
at java.base/java.lang.Thread.run(Thread.java:834)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: io.smallrye.jwt.auth.principal.ParseException: Failed to verify token
at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parse(DefaultJWTTokenParser.java:102)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator.validateClaimsSet(MpJwtValidator.java:41)
... 56 more
Caused by: org.jose4j.jwt.consumer.InvalidJwtException: JWT processing failed. Additional details: [[17] Unable to process JOSE object (cause: org.jose4j.lang.UnresolvableKeyException: Failed to read location as any of JWK, JWKS, PEM; META-INF/resources/publicKey.pem): JsonWebSignature{"kid":"\/privateKey.pem","typ":"JWT","alg":"RS256"}-> **public-key-here**
at org.jose4j.jwt.consumer.JwtConsumer.processContext(JwtConsumer.java:271)
at org.jose4j.jwt.consumer.JwtConsumer.process(JwtConsumer.java:433)
at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parse(DefaultJWTTokenParser.java:70)
... 57 more
Caused by: org.jose4j.lang.UnresolvableKeyException: Failed to read location as any of JWK, JWKS, PEM; META-INF/resources/publicKey.pem
at io.smallrye.jwt.auth.principal.KeyLocationResolver.resolveKey(KeyLocationResolver.java:70)
at org.jose4j.jwt.consumer.JwtConsumer.processContext(JwtConsumer.java:213)
... 59 more
12:48:57 INFO [io.un.re.security]] (executor-thread-1) Failed to authenticate JWT bearer token
smallrye-jwt can do it first before eclipse/microprofile-jwt-auth#129 is addressed
If it is HttpsJwks
then it is only possible to configure the refresh interval from Thorntail
At some stage the parsers may become pluggable but at the moment the pluggability at the factory level seems sufficient, so for now we can just make it very easy to customize specific parsing aspects for the users offering a custom factory
The jose4j method org.jose4j.jwt.consumer.JwtConsumer.processContext(JwtContext)
is called twice from DefaultJWTTokenParser
. First (indirectly) during the call to org.jose4j.jwt.consumer.JwtConsumer.process(String)
and then directly from DefaultJWTTokenParser
after returning from process
.
At the moment the JWT sets are dealt with in two different places. First mp.jwt.publickey.location
is checked if it points to a JWK set resource in KeyLocationResolver
. Next if an internal followMpJwt11Rules
is set then it is assumed that instead of mp.jwt.publickey.location
jwksUri
was set and the keys are loaded not in the resolver but in the parser. So we have two ways to point to JWKs, only one of them is used in smallrye-jwt while the jwksUri
path is used via a followMpJwt11Rules
diversion from Thorntail.
This really needs to change and followMpJwt11Rules
needs to go as it is confusing (and will become more so when we move to newer versions of MP JWT). Instead KeyLocationResolver
should keep all the code for loading the keys, for example, it can check if the location starts from https
etc.
JWTAuthContextInfo
jwksUri
should also be renamed to publicKeyLocation
or similar, otherwise at the moment, if is actually used to load PEM keys as well, it is initialized with mp.jwt.publickey.location
which adds the extra confusion.
I didn't notice this before because I was directly using JsonWebToken
s, but the producer methods in ClaimValueProducer
, JsonValueProducer
, and RawClaimTypeProducer
do not specify a scope, which defaults to @Dependent
. When injecting into @ApplicationScoped
JAX-RS resources (and also @Stateless
resources), the claims are not updated per each request.
When the value of a claim is an array that contains a null entry, a NullPointerException is thrown when the value is added to the JsonArrayBuilder
in JWTCallerPrincipal
.
It looks like jsonValue
in JWTCallerPrincipal.wrapClaimValue()
should be initialized to JsonValue.NULL
instead of null
.
Hi,
I asked in MP-JWT github about a way to configure no verification
for the JWT. It might be something proprietary so I'll try asking here too. Is it possible to inject an un-verified JWT? I had to manually parse (and verify the auth header) instead of just using @Inject
like I think should be possible.
As part of my earlier PR #61 I tried to optimize the way base64 processing is done and pushed it out of JWK processing code to the loadContent ones. This broke the PEM processing which I only caught with Thorntail TCK tests.
I propose simply remove the Base64 decoding attempt as it was only meant originally for JWK but JWKs are not usually get Base64 encoded as the whole (but Base64Url encoded if they included as JOSE header properties).
smallrye-jwt configuration has been significantly enhanced. The documentation needs to reflect it
At the moment, if a path to the custom claim containing the group values points to a non-array, single string, then it is only processed if it is a well known scope
claim which has the space separated values.
The Quarkus discussion around the JHipster integration highlighted a limitation of the above approach, since the custom auth
claim created by JHipster has the comma-separated values.
A new smallrye.jwt.groups-separator
needs to be introduced with the default value " " for the current scope
support to stay as currently is for the users.
To avoid other implementations such as Quarkus MpJwtValidator totally duplicating it.
Syncing the code which is currently duplicated in Quarkus with the one from DefaultJWTCallerPrincipal is also part of this issue
The tokens have to be short-lived in general, this is why, in OIDC/OAuth2 flows, refresh tokens with the longer life span exist, to refresh the ATs and thus minimize the theft risk.
JWT has an expiry claim but it may be set for a long time in the future. Sometimes to simplify the client code issuing the tokens. As such there has to be a property which can block the tokens which have been around for too long
As stated in MP-JWT Spec 1.1,
Relative or non-URL paths supplied as the location are resolved in the following order:
new File(location)
Thread.currentThread().getContextClassLoader().getResource(location)
However the first case is not working.
In my microprofile-config.properties
, I have:
mp.jwt.verify.publickey.location=jwk-signature.json
If I put jwk-signature.json
in the current folder and run
java -jar target/my-quarkus-runner.jar
I get:
2019-07-03 11:32:37,006 WARN [io.sma.jwt.aut.pri.DefaultJWTTokenParser] (executor-thread-1) Token is invalid: JWT processing failed. Additional details: [[17] Unable to process JOSE object (cause: org.jose4j.lang.UnresolvableKeyException: Failed to load a key from: jwk-signature.json): JsonWebSignature{"alg":"RS256","kid":"..."}->...]
This property was introduced in the current SNAPSHOT so changing it now is fine.
smallrye.jwt.path.groups
will allow for a more compact configuration when multiple paths have to be supported, example, the paths to the custom groups
and sub
claims:
path:
groups: a/b
sub: c/d
instead of
groups:
path: a/b
sub:
path: c/d
The producer method is annotated with @ApplicationScoped
but returns Optional
which is declared final. If there is a bean that injects Optional<JWTAuthContextInfo>
the deployment should fail. See 3.11. Unproxyable bean types.
RFC 7662 talks about OAuth2/OIDC servers returning token introspection responses.
Keycloak also implements it: https://issues.jboss.org/browse/KEYCLOAK-2266
Having such a factory will let the users (optionally) integrate with any certified OIDC servers. It will also allow to support the encrypted tokens issued by such servers (which choose to encrypt them) since importing the private keys of these providers into MP-JWT endpoints is not possible.
Right now it is passed as a 2nd parameter to the factory validating the token. Instead the factories which need it should have it injected
Right now it is not cached because Jose4J keeps refreshing the set, but we can still cache if a kid property is set and if the verification fails then recalculate the key.
Right now SmallryeJwtUtils
has a nearly identical code for setting the sub
and group
path properties and DefaultJWTTokenParser
has a nearly identical code for resolving those paths.
In the former case both functions can delegate to the internal one, while in the latter the common function can look for a final segment and let the cast be done in the sub
and groups
path code branches
Currently I'm working on a project with Quarkus and I was stuck on a NullPointerException that
was just logged on the console output.
[io.sm.jw.au.pr.DefaultJWTTokenParser]] (executor-thread-1) Token is invalid: JWT processing failed. Additional details: [[17] Unexpected exception encountered while processing JOSE object (java.lang.NullPointerException): JsonWebSignature{"kid":"....
After some debugging it appeared that I just mistyped the resource name in mp.jwt.verify.publickey.location
.
So I will propose you a little modification to manage this case and avoid the NullPointerException.
This may become an MP-JWT issue, but some initial experiments can be done in smallrye-jwt.
Currently, as far as MP-JWT is concerned it can work well in cases where OIDC client (browser or webserver) acquires an access token and uses them to access RSs which is where MP-JWT helps.
For example, OIDC authorization code flow would typically involve a web server acting as OIDC client, redirecting the user to IDP, getting the authorization code, exchanging it for the access and ID tokens, and using the access token to make the remote RS calls.
Now, if MP-JWT is used in such the OIDC client then it can easily validate either ID or the access token, but it can't redirect the user back to IDP and it can't keep some session state. In fact it may better be done at the Quarkus/Thorntail/etc level, but I'm opening the issue here for some further investigations
For example, Thorntail or Quarkus specific ones, only a minor update to JWTAuthContextInfoProvider.setTokenHeadersAndGroups is needed
It can be possible that the the server itself creates and signs the original JWT token to be used later for the cookie-based authentication (ex, JHipster). To access such tokens via MP JWT Api smallrye-jwt needs to optionally support the hash HS* algorithms which are currently blocked and then a user would just set a whitelist property enabling HS*.
The major change would have to be done in KeyLocationResolver
. It will only be supported for the keys stored in the JWK format, and the verificationKey
property would have to become just a Key
type.
The somewhat unfortunate bit is that the location property is called mp.jwt.publickey.location
, so a smallrye.jwt.secretkey.location
would likely need to be introduced (it is unlikely the secret keys will be supported at the spec level)
I'm using Microprofile JWT for Thorntail (which is using this library) and in my @ApplicationScoped
bean, the principal (JsonWebToken) isn't @RequestScoped
.
According to the specification 1.1 (or even 1.0), "7.1.1. Injection of JsonWebToken", JsonWebToken
needs to be @RequestScoped
, so the current caller is injected in @ApplicationScoped
beans.
I'm not sure if JWTCallerPrincipal
should get a @RequestScoped
-annotation or if the thorntail-library should add a producer or something like this. But current behaviour is dangerous, because a second caller is getting identity from the first one.
So, is this the right place for this issue?
KeyLocationResolver
needs more work to clean it up, and remove the volatile
qualifier from the verificationKey
For example a Keycloak token has its own nested claim for specifying the roles. It would be useful to be able to map it to the MP JWT groups
Using keystores is quite likely the most used option in practice
We're facing a problem in our local environment when trying to get the public key from a non-SSL-protected server:
java.nio.file.InvalidPathException: Illegal char <:> at index 4: http://localhost:30000/auth/realms/test/protocol/openid-connect/certs
at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
at sun.nio.fs.AbstractPath.resolve(AbstractPath.java:53)
at io.quarkus.runner.RuntimeClassLoader.findApplicationResourceContent(RuntimeClassLoader.java:446)
at io.quarkus.runner.RuntimeClassLoader.getResourceAsStream(RuntimeClassLoader.java:149)
at io.smallrye.jwt.auth.principal.KeyLocationResolver.getAsClasspathResource(KeyLocationResolver.java:287)
at io.smallrye.jwt.auth.principal.KeyLocationResolver.readKeyContent(KeyLocationResolver.java:188)
at io.smallrye.jwt.auth.principal.KeyLocationResolver.initializeKeyContent(KeyLocationResolver.java:161)
at io.smallrye.jwt.auth.principal.KeyLocationResolver.(KeyLocationResolver.java:77)
at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.getKeyResolver(DefaultJWTTokenParser.java:229)
at io.smallrye.jwt.auth.principal.DefaultJWTTokenParser.parse(DefaultJWTTokenParser.java:74)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator.validateClaimsSet(MpJwtValidator.java:41)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator.validate(MpJwtValidator.java:35)
at io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator_ClientProxy.validate(MpJwtValidator_ClientProxy.zig:193)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.validateToken(TokenSecurityRealm.java:207)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.getClaims(TokenSecurityRealm.java:195)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.exists(TokenSecurityRealm.java:157)
at org.wildfly.security.auth.realm.token.TokenSecurityRealm$TokenRealmIdentity.getEvidenceVerifySupport(TokenSecurityRealm.java:186)
at org.wildfly.security.auth.server.ServerAuthenticationContext$UnassignedState.verifyEvidence(ServerAuthenticationContext.java:1659)
at org.wildfly.security.auth.server.ServerAuthenticationContext$InactiveState.verifyEvidence(ServerAuthenticationContext.java:1391)
at org.wildfly.security.auth.server.ServerAuthenticationContext.verifyEvidence(ServerAuthenticationContext.java:759)
at org.wildfly.security.auth.server.SecurityDomain.authenticate(SecurityDomain.java:309)
at org.wildfly.security.auth.server.SecurityDomain.authenticate(SecurityDomain.java:270)
at io.quarkus.smallrye.jwt.runtime.auth.JwtIdentityManager.verify(JwtIdentityManager.java:36)
at io.quarkus.smallrye.jwt.runtime.auth.JWTAuthMechanism.authenticate(JWTAuthMechanism.java:53)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:245)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:268)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:231)
at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:125)
at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:99)
at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:92)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PathHandler.handleRequest(PathHandler.java:91)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:270)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:59)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:116)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:113)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$8$1$1.call(UndertowDeploymentRecorder.java:433)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:250)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:59)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:82)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:290)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:665)
at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:224)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
It might be possible that this is only a problem on Windows, because of the different PathParser. I think, at KeyLocationResolver.readKeyContent
it is excepted that getAsClasspathResource
returns with null
if it didn't find anything. But the WindowsPathPatser
instead throws an exception. So the last chance is = new URL(keyLocation).openStream();
isn't reached in my case.
It can help with doing the demos for example, given that the MP JWT spec mentions HTTPS but without restricting it to JWKS.
Utilizing JwtConsumerBuilder.setExpectedAudience(Boolean, String...)
. The logic should align with what is currently done to require/validate the issuer claim.
smallrye.jwt.verify.audiences
(Optional<Set<String>>
)
smallrye.jwt.verify.requireaud
(Optional<Boolean>
)
Potential configurations if incorporated into specification:
mp.jwt.verify.audiences
mp.jwt.verify.requireaud
Edit: make expected audiences property plural to align with JOSE4J API and OpenLiberty implementation.
For example, having smallrye.jwt.required.claims
=a,b,c
would fail the verification if at least one of these claims is missing
Right now the tck module tests are not running the real TCK tests against a server, so the proposal is to move the current tests into a new testsuite/basic
module and at some later stage a testsuite/tck can be added as well (may be the TCK can be run against WildFly and the authentication mechanism Mike Edgar is working upon, etc).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.