{"record":{"id":"835544ef33457367","repo":"quarkusio/quarkus","slug":"truststore-with-configured-password-which-keeps-th","errorCode":null,"errorMessage":"Truststore with configured password which keeps thumbprints of the trusted certificates must be present","messagePattern":"Truststore with configured password which keeps thumbprints of the trusted certificates must be present","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"critical","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CertChainPublicKeyResolver.java","lineNumber":30,"sourceCode":"import org.jose4j.lang.UnresolvableKeyException;\n\nimport io.quarkus.oidc.OidcTenantConfig;\nimport io.quarkus.oidc.TokenCertificateValidator;\nimport io.quarkus.runtime.configuration.ConfigurationException;\nimport io.quarkus.vertx.http.runtime.security.HttpSecurityUtils;\nimport io.vertx.ext.auth.impl.CertificateHelper;\n\npublic class CertChainPublicKeyResolver implements RefreshableVerificationKeyResolver {\n    private static final Logger LOG = Logger.getLogger(OidcProvider.class);\n    final OidcTenantConfig oidcConfig;\n    final Set<String> thumbprints;\n    final Optional<String> expectedLeafCertificateName;\n    final List<TokenCertificateValidator> certificateValidators;\n\n    public CertChainPublicKeyResolver(OidcTenantConfig oidcConfig) {\n        this.oidcConfig = oidcConfig;\n        if (oidcConfig.certificateChain().trustStorePassword().isEmpty()) {\n            throw new ConfigurationException(\n                    \"Truststore with configured password which keeps thumbprints of the trusted certificates must be present\");\n        }\n        this.thumbprints = TrustStoreUtils.getTrustedCertificateThumbprints(\n                oidcConfig.certificateChain().trustStoreFile().get(),\n                oidcConfig.certificateChain().trustStorePassword().get(),\n                oidcConfig.certificateChain().trustStoreCertAlias(),\n                oidcConfig.certificateChain().trustStoreFileType());\n        this.expectedLeafCertificateName = oidcConfig.certificateChain().leafCertificateName();\n        this.certificateValidators = TenantFeatureFinder.find(oidcConfig, TokenCertificateValidator.class);\n    }\n\n    @Override\n    public Key resolveKey(JsonWebSignature jws, List<JsonWebStructure> nestingContext)\n            throws UnresolvableKeyException {\n\n        try {\n            List<X509Certificate> chain = jws.getCertificateChainHeaderValue();\n            if (chain == null) {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CertChainPublicKeyResolver.java#L12-L48","documentation":"Quarkus OIDC throws this ConfigurationException at startup when a tenant is configured with certificate-chain-bound token verification (quarkus.oidc.certificate-chain.*) but no truststore password is set. The CertChainPublicKeyResolver needs the password to load the truststore and compute thumbprints of trusted certificates. Without it, certificate chain verification cannot work, so configuration is rejected immediately.","triggerScenarios":"Tenant config sets quarkus.oidc.certificate-chain.trust-store-file (or a trustStoreFile is programmatically provided) but quarkus.oidc.certificate-chain.trust-store-password is empty/unset; OidcConfigurationConfigBuilder constructs CertChainPublicKeyResolver(oidcConfig).","commonSituations":"Copying a truststore config example and omitting the password property; building OidcTenantConfig programmatically and leaving trustStorePassword() as Optional.empty(); secrets injection (env var/K8s secret) not wired so the property resolves empty.","solutions":["Set quarkus.oidc.certificate-chain.trust-store-password=<password> (or the tenant-scoped equivalent) in application.properties.","If configuring programmatically, set certificateChain().trustStorePassword() to a non-empty value in the OidcTenantConfig builder.","Verify the password is actually injected (env var, secret) and not left empty at build time."],"exampleFix":"// before\nquarkus.oidc.tenant-a.certificate-chain.trust-store-file=/conf/truststore.p12\n// after\nquarkus.oidc.tenant-a.certificate-chain.trust-store-file=/conf/truststore.p12\nquarkus.oidc.tenant-a.certificate-chain.trust-store-password=secret","handlingStrategy":"validation","validationCode":"if (config.certificateChain().trustStoreFile().isPresent()\n        && config.certificateChain().trustStorePassword().isEmpty()) {\n    throw new IllegalStateException(\n        \"certificate-chain.trust-store-file requires certificate-chain.trust-store-password\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    startApplication();\n} catch (ConfigurationException e) {\n    if (e.getMessage().contains(\"Truststore with configured password\")) {\n        log.error(\"OIDC certificate-chain truststore password missing; set quarkus.oidc.certificate-chain.trust-store-password\");\n    }\n    throw e;\n}","preventionTips":["Always set trust-store-password together with trust-store-file in the same config block.","Add a startup smoke test or CI config check that builds the tenant config.","Use a config profile and assert required OIDC properties exist before deploy."],"tags":["oidc","configuration","truststore"],"backgroundTag":"missing-config-property","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"}