{"record":{"id":"9798136c04bb6248","repo":"quarkusio/quarkus","slug":"wrong-leaf-certificate-common-name","errorCode":null,"errorMessage":"Wrong leaf certificate common name","messagePattern":"Wrong leaf certificate common name","errorType":"exception","errorClass":"UnresolvableKeyException","httpStatus":401,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CertChainPublicKeyResolver.java","lineNumber":89,"sourceCode":"                LOG.error(\"Thumprint of the root chain certificate is invalid\");\n                throw new UnresolvableKeyException(\"Thumprint of the root chain certificate is invalid\");\n            }\n\n            // Run custom validators if any\n            if (!certificateValidators.isEmpty()) {\n                LOG.debug(\"Running custom TokenCertificateValidators\");\n                for (TokenCertificateValidator validator : certificateValidators) {\n                    validator.validate(oidcConfig, chain, jws.getUnverifiedPayload());\n                }\n            }\n\n            // Finally, check the leaf certificate if required\n            if (expectedLeafCertificateName.isPresent()) {\n                // Compare the leaf certificate common name against the configured value\n                String leafCertificateName = HttpSecurityUtils.getCommonName(chain.get(0).getSubjectX500Principal());\n                if (!expectedLeafCertificateName.get().equals(leafCertificateName)) {\n                    LOG.errorf(\"Wrong leaf certificate common name: %s\", leafCertificateName);\n                    throw new UnresolvableKeyException(\"Wrong leaf certificate common name\");\n                }\n            } else if (certificateValidators.isEmpty()) {\n                // No custom validators are registered and no leaf certificate CN is configured\n                // Check that the truststore contains a leaf certificate thumbprint\n                LOG.debug(\"Checking a thumbprint of the leaf chain certificate\");\n                String thumbprint = TrustStoreUtils.calculateThumprint(chain.get(0));\n                if (!thumbprints.contains(thumbprint)) {\n                    LOG.error(\"Thumprint of the leaf chain certificate is invalid\");\n                    throw new UnresolvableKeyException(\"Thumprint of the leaf chain certificate is invalid\");\n                }\n            }\n\n            return chain.get(0).getPublicKey();\n        } catch (UnresolvableKeyException ex) {\n            throw ex;\n        } catch (Exception ex) {\n            throw new UnresolvableKeyException(\"Invalid certificate chain\", ex);\n        }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CertChainPublicKeyResolver.java#L71-L107","documentation":"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.","triggerScenarios":"resolveKey() sees expectedLeafCertificateName present and HttpSecurityUtils.getCommonName(chain.get(0).getSubjectX500Principal()) differs from the configured value.","commonSituations":"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.","solutions":["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).","If the leaf certificate was rotated, update the configured CN to the new certificate's subject CN.","Alternatively, register a custom TokenCertificateValidator and remove the leaf-certificate-name constraint if more flexible validation is needed.","Verify the token actually comes from the expected issuer, not a different tenant's provider."],"exampleFix":"// before\nquarkus.oidc.certificate-chain.leaf-certificate-name=old-issuer.example.com\n// after\nquarkus.oidc.certificate-chain.leaf-certificate-name=new-issuer.example.com","handlingStrategy":"validation","validationCode":"String cn = HttpSecurityUtils.getCommonName(new X509CertImpl(leaf.getEncoded()).getSubjectX500Principal());\nif (!configuredLeafName.equals(cn)) {\n    log.warnf(\"Configured leaf-certificate-name %s does not match token leaf CN %s\", configuredLeafName, cn);\n}","typeGuard":null,"tryCatchPattern":"try {\n    return jwtVerify(token);\n} catch (UnresolvableKeyException e) {\n    if (\"Wrong leaf certificate common name\".equals(e.getMessage())) {\n        log.error(\"Token leaf CN differs from quarkus.oidc.certificate-chain.leaf-certificate-name; update config\");\n    }\n    throw e;\n}","preventionTips":["Copy the leaf CN exactly from the issuer's current certificate (openssl x509 -noout -subject).","Update leaf-certificate-name as part of issuer certificate rotation runbooks.","Log the actual leaf CN in a test environment before pinning it in production config."],"tags":["oidc","certificate-chain","common-name","leaf-certificate"],"backgroundTag":"certificate-cn-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}