{"record":{"id":"bffbd17917871188","repo":"quarkusio/quarkus","slug":"both-public-key-and-certificate-chain-verification","errorCode":null,"errorMessage":"Both public key and certificate chain verification modes are enabled","messagePattern":"Both public key and certificate chain verification modes are enabled","errorType":"validation","errorClass":"io.quarkus.runtime.configuration.ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":180,"sourceCode":"        LOG.debugf(\n                \"'%s' tenant is not initialized: '%s'. Access to resources protected by this tenant will fail.\",\n                tenantId, t.getMessage());\n        return t;\n    }\n\n    @SuppressWarnings(\"resource\")\n    private Uni<TenantConfigContext> createTenantContext(OidcTenantConfig oidcTenantConfig,\n            boolean checkNamedTenants, String tenantId) {\n        final OidcTenantConfig oidcConfig = OidcUtils.resolveProviderConfig(oidcTenantConfig);\n\n        if (!oidcConfig.tenantEnabled()) {\n            LOG.debugf(\"'%s' tenant configuration is disabled\", tenantId);\n            return TenantConfigContext.createReady(new OidcProvider(null, null, null), oidcConfig);\n        }\n\n        if (oidcConfig.authServerUrl().isEmpty()) {\n            if (oidcConfig.publicKey().isPresent() && oidcConfig.certificateChain().trustStoreFile().isPresent()) {\n                throw new ConfigurationException(\"Both public key and certificate chain verification modes are enabled\");\n            }\n            if (oidcConfig.publicKey().isPresent()) {\n                return createTenantContextFromPublicKey(oidcConfig);\n            }\n\n            if (oidcConfig.certificateChain().trustStoreFile().isPresent()) {\n                return createTenantContextToVerifyCertChain(oidcConfig);\n            }\n        }\n\n        try {\n            if (oidcConfig.authServerUrl().isEmpty()) {\n                if (DEFAULT_TENANT_ID.equals(oidcConfig.tenantId().get())) {\n                    ArcContainer container = Arc.container();\n                    if (container != null\n                            && (container.instance(TenantConfigResolver.class).isAvailable() || checkNamedTenants)) {\n                        LOG.debugf(\"Default tenant is not configured and will be disabled\"\n                                + \" because either 'TenantConfigResolver' which will resolve tenant configurations is registered\"","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L162-L198","documentation":"A tenant may verify tokens with either a locally configured public key or a certificate-chain trust store, but not both — they are alternative offline verification modes and using both is contradictory. TenantContextFactory.createTenantContext throws this ConfigurationException when, for a tenant with no auth-server-url, both quarkus.oidc.public-key and quarkus.oidc.certificate-chain.trust-store-file are set.","triggerScenarios":"Creating a tenant context for a tenant without auth-server-url where both oidcConfig.publicKey().isPresent() and oidcConfig.certificateChain().trustStoreFile().isPresent() — i.e. both quarkus.oidc.public-key and quarkus.oidc.certificate-chain.trust-store-file (tenant-scoped variants included) are configured.","commonSituations":"Switching from public-key verification to certificate-chain verification but leaving the old public-key property behind; merging tenant config from two sources (application.properties + profile/env) so both modes end up enabled; a shared config template containing both keys.","solutions":["Remove the quarkus.oidc.public-key property if you intend to verify with the certificate chain trust store.","Remove the quarkus.oidc.certificate-chain.trust-store-file property (and related cert-chain settings) if you intend to verify with the public key.","If you actually meant to talk to an OIDC provider, set quarkus.oidc.auth-server-url and remove both offline verification options."],"exampleFix":"// before (application.properties)\nquarkus.oidc.public-key=MIIBIjANBg...\nquarkus.oidc.certificate-chain.trust-store-file=/etc/certs/ca.p12\n\n// after\nquarkus.oidc.certificate-chain.trust-store-file=/etc/certs/ca.p12","handlingStrategy":"validation","validationCode":"boolean publicKeySet = System.getProperty(\"quarkus.oidc.public-key\") != null;\nboolean chainSet = System.getProperty(\"quarkus.oidc.certificate-chain.trust-store-file\") != null;\nif (publicKeySet && chainSet) {\n    throw new IllegalStateException(\"Choose either public-key or certificate-chain verification, not both\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When migrating verification modes, grep config files for leftover quarkus.oidc.public-key or certificate-chain entries.","Document per-environment which offline verification mode is used.","Avoid combining env-var config overlays that can enable both modes simultaneously."],"tags":["oidc","configuration","public-key","certificate-chain","startup"],"backgroundTag":"conflicting-verification-config","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"}