{"record":{"id":"e87cd05e4d2f50a6","repo":"quarkusio/quarkus","slug":"token-issued-to-client-s-does-not-have-a-matching","errorCode":null,"errorMessage":"Token issued to client %s 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","messagePattern":"Token issued to client (.+?) 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","errorType":"exception","errorClass":"AuthenticationFailedException","httpStatus":401,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java","lineNumber":399,"sourceCode":"                                            resolver, true, issuedAtRequired));\n                        } catch (Throwable t) {\n                            return Uni.createFrom().failure(t);\n                        }\n                    }\n\n                });\n    }\n\n    public Uni<TokenIntrospection> introspectToken(String token, TokenType tokenType, Long expiresIn,\n            boolean fallbackFromJwkMatch) {\n        if (client.getMetadata().getIntrospectionUri() == null) {\n            String errorMessage = String.format(\"Token issued to client %s \"\n                    + (fallbackFromJwkMatch ? \"does not have a matching verification key and it \" : \"\")\n                    + \"can not be introspected because the introspection endpoint address is unknown - \"\n                    + \"please check if your OpenId Connect Provider supports the token introspection\",\n                    oidcConfig.clientId().get());\n\n            throw new AuthenticationFailedException(errorMessage, tokenMap(token, tokenType));\n        }\n        return client.introspectAccessToken(token).onItemOrFailure()\n                .transform(new BiFunction<TokenIntrospection, Throwable, TokenIntrospection>() {\n\n                    @Override\n                    public TokenIntrospection apply(TokenIntrospection introspectionResult, Throwable t) {\n                        if (t != null) {\n                            throw new AuthenticationFailedException(t, tokenMap(token, tokenType));\n                        }\n                        Long introspectionExpiresIn = introspectionResult.getLong(OidcConstants.INTROSPECTION_TOKEN_EXP);\n                        if (introspectionExpiresIn == null && expiresIn != null) {\n                            // expires_in is relative to the current time\n                            introspectionExpiresIn = now() + expiresIn;\n                        }\n                        if (!introspectionResult.isActive()) {\n                            verifyTokenExpiry(token, tokenType, introspectionExpiresIn);\n                            throw new AuthenticationFailedException(\n                                    String.format(\"Token issued to client %s is not active\", oidcConfig.clientId().get()),","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java#L381-L417","documentation":"When a JWT cannot be verified locally (no matching JWK/public key) Quarkus falls back to remote introspection. This AuthenticationFailedException is thrown when the fallback is needed but the introspection endpoint URI is unknown (absent from discovery metadata or config), so the token cannot be verified at all.","triggerScenarios":"Token signed with a key not present in the fetched JWKS (kid mismatch / rotated keys not refreshed), combined with no quarkus.oidc.introspection-uri configured and the provider's well-known metadata lacking an introspection endpoint.","commonSituations":"IdP rotated signing keys before JWKS refresh; provider (e.g. some Auth0 setups) does not advertise introspection_endpoint; using public-key-only config then receiving tokens signed with a different key.","solutions":["Set quarkus.oidc.introspection-uri=<provider introspection URL> explicitly.","Force JWKS refresh (quarkus.oidc.token.forced-jwk-refresh-interval) or restart so the rotated key is picked up.","Verify the token's kid matches a key the app is configured to trust.","Update provider client config so tokens are signed with the advertised/expected key."],"exampleFix":"// before\n# (no introspection uri; provider metadata lacks one)\n// after\nquarkus.oidc.introspection-uri=https://idp.example.com/protocol/openid-connect/token/introspect","handlingStrategy":"validation","validationCode":"if (config.introspectionUri().isEmpty()\n        && provider.getMetadata().getIntrospectionUri() == null) {\n    LOG.warn(\"No introspection endpoint configured; JWKS misses will be unrecoverable\");\n}","typeGuard":"boolean canFallbackToIntrospection(OidcTenantConfig cfg, OIDCMetadata meta) {\n    return cfg.introspectionUri().isPresent() || meta.getIntrospectionUri() != null;\n}","tryCatchPattern":"try {\n    return verifyOrIntrospect(token);\n} catch (AuthenticationFailedException e) {\n    // trigger forced JWKS refresh or surface config guidance\n}","preventionTips":["Set quarkus.oidc.introspection-uri explicitly when the provider's metadata lacks an introspection endpoint","Keep JWKS refresh enabled and monitor key rotation at the IdP","Verify kid values of issued tokens match keys discoverable via jwks-uri or public-key"],"tags":["oidc","introspection","jwks","key-rotation"],"backgroundTag":"token-verification-key-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}