{"record":{"id":"60f59ed0da9264f6","repo":"quarkusio/quarkus","slug":"only-one-of-jwt-secret-or-jwt-private-key-authenti","errorCode":null,"errorMessage":"Only one of JWT secret or JWT private key authentication methods can be configured, but '%1$scredentials.jwt' has both a JWT secret and a JWT key property set","messagePattern":"Only one of JWT secret or JWT private key authentication methods can be configured, but '%1\\$scredentials\\.jwt' has both a JWT 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":209,"sourceCode":"                                    + \" but '%1$scredentials' has both a client secret and a JWT secret property set\",\n                            configPrefix));\n        }\n        int jwtKeyPropsCount = (creds.jwt().key().isPresent() ? 1 : 0)\n                + (creds.jwt().keyFile().isPresent() ? 1 : 0)\n                + (creds.jwt().keyStoreFile().isPresent() ? 1 : 0);\n        if (jwtKeyPropsCount > 1) {\n            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()));","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java#L191-L227","documentation":"A JWT client assertion can be signed either with a secret (HMAC) or with a private key (RSA/EC), never both. verifyCommonConfiguration detects that credentials.jwt.secret (jwtSecretConfigured) and a JWT key property (jwtKeyConfigured) are both present and fails startup, because it could not decide which signing method to use for the client JWT.","triggerScenarios":"At startup, both a secret (credentials.jwt.secret) and one of credentials.jwt.key / key-file / key-store-file are set under the same config prefix in verifyCommonConfiguration.","commonSituations":"Adding a private key to a config that already used secret-based authentication (client_secret_jwt) for stronger security but forgetting to delete the secret; merging property files; a template config that includes both options.","solutions":["Decide the auth method: if using private-key JWT, delete credentials.jwt.secret; if using secret JWT, delete the credentials.jwt.key* property","Keep exactly one signing mechanism under the given quarkus.oidc[-client].credentials.jwt prefix","Check environment variables/config source overrides that may inject the second property"],"exampleFix":"# before\nquarkus.oidc-client.credentials.jwt.secret=shared-secret\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 secret = ConfigProvider.getConfig().getOptionalValue(\"quarkus.oidc-client.credentials.jwt.secret\", String.class).isPresent();\nboolean key = ConfigProvider.getConfig().getOptionalValue(\"quarkus.oidc-client.credentials.jwt.key-file\", String.class).isPresent();\nif (secret && key) throw new IllegalStateException(\"Choose either jwt secret or jwt private key, not both\");","typeGuard":null,"tryCatchPattern":"try {\n    start();\n} catch (ConfigurationException e) {\n    if (e.getMessage().contains(\"both a JWT secret and a JWT key\")) log.error(\"Remove jwt.secret or the jwt key property\");\n    throw e;\n}","preventionTips":["Document which auth method each service uses; never template both secret and key properties","After migrating auth methods, diff and delete obsolete properties","Audit env vars/config sources that may inject a second property"],"tags":["quarkus","oidc","configuration","jwt"],"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"}