quarkusio/quarkus · error · AuthenticationFailedException

Token issued to client %s does not have a matching verificat

Error message

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

What it means

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.

Source

Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java:399

                                            resolver, true, issuedAtRequired));
                        } catch (Throwable t) {
                            return Uni.createFrom().failure(t);
                        }
                    }

                });
    }

    public Uni<TokenIntrospection> introspectToken(String token, TokenType tokenType, Long expiresIn,
            boolean fallbackFromJwkMatch) {
        if (client.getMetadata().getIntrospectionUri() == null) {
            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(errorMessage, tokenMap(token, tokenType));
        }
        return client.introspectAccessToken(token).onItemOrFailure()
                .transform(new BiFunction<TokenIntrospection, Throwable, TokenIntrospection>() {

                    @Override
                    public TokenIntrospection apply(TokenIntrospection introspectionResult, Throwable t) {
                        if (t != null) {
                            throw new AuthenticationFailedException(t, tokenMap(token, tokenType));
                        }
                        Long introspectionExpiresIn = introspectionResult.getLong(OidcConstants.INTROSPECTION_TOKEN_EXP);
                        if (introspectionExpiresIn == null && expiresIn != null) {
                            // expires_in is relative to the current time
                            introspectionExpiresIn = now() + expiresIn;
                        }
                        if (!introspectionResult.isActive()) {
                            verifyTokenExpiry(token, tokenType, introspectionExpiresIn);
                            throw new AuthenticationFailedException(
                                    String.format("Token issued to client %s is not active", oidcConfig.clientId().get()),

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set quarkus.oidc.introspection-uri=<provider introspection URL> explicitly.
  2. Force JWKS refresh (quarkus.oidc.token.forced-jwk-refresh-interval) or restart so the rotated key is picked up.
  3. Verify the token's kid matches a key the app is configured to trust.
  4. Update provider client config so tokens are signed with the advertised/expected key.

Example fix

// before
# (no introspection uri; provider metadata lacks one)
// after
quarkus.oidc.introspection-uri=https://idp.example.com/protocol/openid-connect/token/introspect
Defensive patterns

Strategy: validation

Validate before calling

if (config.introspectionUri().isEmpty()
        && provider.getMetadata().getIntrospectionUri() == null) {
    LOG.warn("No introspection endpoint configured; JWKS misses will be unrecoverable");
}

Type guard

boolean canFallbackToIntrospection(OidcTenantConfig cfg, OIDCMetadata meta) {
    return cfg.introspectionUri().isPresent() || meta.getIntrospectionUri() != null;
}

Try / catch

try {
    return verifyOrIntrospect(token);
} catch (AuthenticationFailedException e) {
    // trigger forced JWKS refresh or surface config guidance
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e87cd05e4d2f50a6. Report an issue: GitHub.