{"record":{"id":"b65781e4313c1d11","repo":"quarkusio/quarkus","slug":"only-one-of-client-secret-or-jwt-private-key-authe","errorCode":null,"errorMessage":"Only one of client secret or JWT private key authentication methods can be configured, but '%1$scredentials' has both a client secret and a JWT key property set","messagePattern":"Only one of client secret or JWT private key authentication methods can be configured, but '%1\\$scredentials' has both a client secret and a JWT key property set","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java","lineNumber":216,"sourceCode":"            throw new ConfigurationException(\n                    String.format(\n                            \"Only one of '%1$scredentials.jwt.key', '%1$scredentials.jwt.key-file'\"\n                                    + \" or '%1$scredentials.jwt.key-store-file' can be configured\",\n                            configPrefix));\n        }\n        boolean jwtKeyConfigured = jwtKeyPropsCount == 1;\n        boolean jwtBearerOrSpiffe = creds.jwt().source() == Source.BEARER\n                || creds.jwt().source() == Source.SPIFFE_JWT;\n\n        if (jwtSecretConfigured && jwtKeyConfigured) {\n            throw new ConfigurationException(\n                    String.format(\n                            \"Only one of JWT secret or JWT private key authentication methods can be configured,\"\n                                    + \" but '%1$scredentials.jwt' has both a JWT secret and a JWT key property set\",\n                            configPrefix));\n        }\n        if (clientSecretConfigured && jwtKeyConfigured) {\n            throw new ConfigurationException(\n                    String.format(\n                            \"Only one of client secret or JWT private key authentication methods can be configured,\"\n                                    + \" but '%1$scredentials' has both a client secret and a JWT key property set\",\n                            configPrefix));\n        }\n        if (clientSecretConfigured && jwtBearerOrSpiffe) {\n            throw new ConfigurationException(\n                    String.format(\n                            \"Only one of client secret or JWT bearer/SPIFFE authentication methods can be configured,\"\n                                    + \" but '%1$scredentials' has both a client secret and '%1$scredentials.jwt.source=%2$s' set\",\n                            configPrefix, creds.jwt().source().toString().toLowerCase()));\n        }\n        if (jwtKeyConfigured && jwtBearerOrSpiffe) {\n            throw new ConfigurationException(\n                    String.format(\n                            \"Only one of JWT private key or JWT bearer/SPIFFE authentication methods can be configured,\"\n                                    + \" but '%1$scredentials' has both a JWT key property and '%1$scredentials.jwt.source=%2$s' set\",\n                            configPrefix, creds.jwt().source().toString().toLowerCase()));","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java#L198-L234","documentation":"The client secret can be used for basic/POST client authentication or to sign a secret-based JWT, while credentials.jwt.key* selects private-key JWT authentication. verifyCommonConfiguration throws when a client secret and a JWT private-key property are configured together, as only one authentication method can apply to the token request.","triggerScenarios":"At startup, credentials.client.secret (or similar client secret property) is set and simultaneously one of credentials.jwt.key, credentials.jwt.key-file, credentials.jwt.key-store-file is set under the same config prefix.","commonSituations":"Hardening a secret-authenticated client by adding a JWT key without removing the secret; provider migration where both old and new credential styles remain; duplicated config blocks in named-provider sections.","solutions":["Choose one method: keep the client secret and remove credentials.jwt.key*, or keep the key property and remove credentials.client.secret","Verify no profile or env var re-introduces the removed property","Restart and confirm startup passes the configuration verification"],"exampleFix":"# before\nquarkus.oidc-client.credentials.client-secret.value=secret123\nquarkus.oidc-client.credentials.jwt.key-file=/etc/certs/key.pem\n\n# after\nquarkus.oidc-client.credentials.jwt.key-file=/etc/certs/key.pem","handlingStrategy":"validation","validationCode":"boolean clientSecret = ConfigProvider.getConfig().getOptionalValue(\"quarkus.oidc-client.credentials.client-secret.value\", String.class).isPresent();\nboolean jwtKey = ConfigProvider.getConfig().getOptionalValue(\"quarkus.oidc-client.credentials.jwt.key-file\", String.class).isPresent();\nif (clientSecret && jwtKey) throw new IllegalStateException(\"Use either a client secret or a JWT private key\");","typeGuard":null,"tryCatchPattern":"try {\n    start();\n} catch (ConfigurationException e) {\n    if (e.getMessage().contains(\"both a client secret and a JWT key\")) log.error(\"Drop the client-secret or the jwt.key property\");\n    throw e;\n}","preventionTips":["Pick one client authentication method per provider and note it in config comments","Review merged/named provider blocks for leftover credentials","Run a startup smoke test in CI to catch config verification failures early"],"tags":["quarkus","oidc","configuration"],"backgroundTag":"conflicting-configuration-properties","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"}