diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java index 5d61792865d2c9..90fac732c94267 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java @@ -408,12 +408,12 @@ private Uni verifyTokenUni(TenantConfigContext resolved } } LOG.debug("Starting the opaque token introspection"); - return introspectTokenUni(resolvedContext, token); + return introspectTokenUni(resolvedContext, token, false); } else if (resolvedContext.provider.getMetadata().getJsonWebKeySetUri() == null || resolvedContext.oidcConfig.token.requireJwtIntrospectionOnly) { // Verify JWT token with the remote introspection LOG.debug("Starting the JWT token introspection"); - return introspectTokenUni(resolvedContext, token); + return introspectTokenUni(resolvedContext, token, false); } else { // Verify JWT token with the local JWK keys with a possible remote introspection fallback try { @@ -442,32 +442,44 @@ private Uni verifySelfSignedTokenUni(TenantConfigContex private Uni refreshJwksAndVerifyTokenUni(TenantConfigContext resolvedContext, String token, boolean enforceAudienceVerification) { return resolvedContext.provider.refreshJwksAndVerifyJwtToken(token, enforceAudienceVerification) - .onFailure(f -> f.getCause() instanceof UnresolvableKeyException - && resolvedContext.oidcConfig.token.allowJwtIntrospection) - .recoverWithUni(f -> introspectTokenUni(resolvedContext, token)); + .onFailure(f -> fallbackToIntrospectionIfNoMatchingKey(f, resolvedContext)) + .recoverWithUni(f -> introspectTokenUni(resolvedContext, token, true)); } - private Uni introspectTokenUni(TenantConfigContext resolvedContext, final String token) { + private static boolean fallbackToIntrospectionIfNoMatchingKey(Throwable f, TenantConfigContext resolvedContext) { + LOG.debug("No matching verificaton key is found, attempting to introspect the token"); + if (f.getCause() instanceof UnresolvableKeyException && resolvedContext.oidcConfig.token.allowJwtIntrospection) { + return true; + } else { + LOG.debug("JWT token introspection is disabled"); + return false; + } + + } + + private Uni introspectTokenUni(TenantConfigContext resolvedContext, final String token, + boolean fallbackFromJwkMatch) { TokenIntrospectionCache tokenIntrospectionCache = tenantResolver.getTokenIntrospectionCache(); Uni tokenIntrospectionUni = tokenIntrospectionCache == null ? null : tokenIntrospectionCache .getIntrospection(token, resolvedContext.oidcConfig, getIntrospectionRequestContext); if (tokenIntrospectionUni == null) { - tokenIntrospectionUni = newTokenIntrospectionUni(resolvedContext, token); + tokenIntrospectionUni = newTokenIntrospectionUni(resolvedContext, token, fallbackFromJwkMatch); } else { tokenIntrospectionUni = tokenIntrospectionUni.onItem().ifNull() .switchTo(new Supplier>() { @Override public Uni get() { - return newTokenIntrospectionUni(resolvedContext, token); + return newTokenIntrospectionUni(resolvedContext, token, fallbackFromJwkMatch); } }); } return tokenIntrospectionUni.onItem().transform(t -> new TokenVerificationResult(null, t)); } - private Uni newTokenIntrospectionUni(TenantConfigContext resolvedContext, String token) { - Uni tokenIntrospectionUni = resolvedContext.provider.introspectToken(token); + private Uni newTokenIntrospectionUni(TenantConfigContext resolvedContext, String token, + boolean fallbackFromJwkMatch) { + Uni tokenIntrospectionUni = resolvedContext.provider.introspectToken(token, fallbackFromJwkMatch); if (tenantResolver.getTokenIntrospectionCache() == null || !resolvedContext.oidcConfig.allowTokenIntrospectionCache) { return tokenIntrospectionUni; } else { diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java index 9757fbd93b4f02..9df7e34a2c4a30 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java @@ -267,13 +267,15 @@ public Uni apply(Void v) { }); } - public Uni introspectToken(String token) { + public Uni introspectToken(String token, boolean fallbackFromJwkMatch) { if (client.getMetadata().getIntrospectionUri() == null) { - LOG.debugf( - "Token issued to client %s can not be introspected because the introspection endpoint address is unknown - " - + "please check if your OpenId Connect Provider supports the token introspection", + String errorMessage = String.format("Token issued to client %s " + + (fallbackFromJwkMatch ? "does not have a matching verification key and it " : "") + + "can not be introspected because the introspection endpoint address is unknown - " + + "please check if your OpenId Connect Provider supports the token introspection", oidcConfig.clientId.get()); - throw new AuthenticationFailedException(); + + throw new AuthenticationFailedException(errorMessage); } return client.introspectToken(token).onItemOrFailure() .transform(new BiFunction() {