quarkusio/quarkus · error · UnresolvableKeyException

Wrong leaf certificate common name

Error message

Wrong leaf certificate common name

What it means

If a leaf certificate common name is configured (quarkus.oidc.certificate-chain.leaf-certificate-name), the resolver compares it against the CN of the leaf (first) certificate in the token's x5c chain. A mismatch means the token was signed with a certificate whose subject does not match the expected issuer certificate, so verification is refused with UnresolvableKeyException.

Source

Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CertChainPublicKeyResolver.java:89

                LOG.error("Thumprint of the root chain certificate is invalid");
                throw new UnresolvableKeyException("Thumprint of the root chain certificate is invalid");
            }

            // Run custom validators if any
            if (!certificateValidators.isEmpty()) {
                LOG.debug("Running custom TokenCertificateValidators");
                for (TokenCertificateValidator validator : certificateValidators) {
                    validator.validate(oidcConfig, chain, jws.getUnverifiedPayload());
                }
            }

            // Finally, check the leaf certificate if required
            if (expectedLeafCertificateName.isPresent()) {
                // Compare the leaf certificate common name against the configured value
                String leafCertificateName = HttpSecurityUtils.getCommonName(chain.get(0).getSubjectX500Principal());
                if (!expectedLeafCertificateName.get().equals(leafCertificateName)) {
                    LOG.errorf("Wrong leaf certificate common name: %s", leafCertificateName);
                    throw new UnresolvableKeyException("Wrong leaf certificate common name");
                }
            } else if (certificateValidators.isEmpty()) {
                // No custom validators are registered and no leaf certificate CN is configured
                // Check that the truststore contains a leaf certificate thumbprint
                LOG.debug("Checking a thumbprint of the leaf chain certificate");
                String thumbprint = TrustStoreUtils.calculateThumprint(chain.get(0));
                if (!thumbprints.contains(thumbprint)) {
                    LOG.error("Thumprint of the leaf chain certificate is invalid");
                    throw new UnresolvableKeyException("Thumprint of the leaf chain certificate is invalid");
                }
            }

            return chain.get(0).getPublicKey();
        } catch (UnresolvableKeyException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new UnresolvableKeyException("Invalid certificate chain", ex);
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set quarkus.oidc.certificate-chain.leaf-certificate-name to the exact CN of the current leaf certificate (inspect with: openssl x509 -noout -subject -in leaf.crt).
  2. If the leaf certificate was rotated, update the configured CN to the new certificate's subject CN.
  3. Alternatively, register a custom TokenCertificateValidator and remove the leaf-certificate-name constraint if more flexible validation is needed.
  4. Verify the token actually comes from the expected issuer, not a different tenant's provider.

Example fix

// before
quarkus.oidc.certificate-chain.leaf-certificate-name=old-issuer.example.com
// after
quarkus.oidc.certificate-chain.leaf-certificate-name=new-issuer.example.com
Defensive patterns

Strategy: validation

Validate before calling

String cn = HttpSecurityUtils.getCommonName(new X509CertImpl(leaf.getEncoded()).getSubjectX500Principal());
if (!configuredLeafName.equals(cn)) {
    log.warnf("Configured leaf-certificate-name %s does not match token leaf CN %s", configuredLeafName, cn);
}

Try / catch

try {
    return jwtVerify(token);
} catch (UnresolvableKeyException e) {
    if ("Wrong leaf certificate common name".equals(e.getMessage())) {
        log.error("Token leaf CN differs from quarkus.oidc.certificate-chain.leaf-certificate-name; update config");
    }
    throw e;
}

Prevention

When it happens

Trigger: resolveKey() sees expectedLeafCertificateName present and HttpSecurityUtils.getCommonName(chain.get(0).getSubjectX500Principal()) differs from the configured value.

Common situations: Wrong value configured (typo, missing prefix/suffix in DN); issuer rotated the leaf certificate and the new one has a different CN; the same truststore is shared across tenants expecting different leaf names.

Understand the failure class

Related errors


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