quarkusio/quarkus · error · ConfigurationException
Only one of client secret or JWT private key authentication
Error message
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
What it means
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.
Source
Thrown at extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java:216
throw new ConfigurationException(
String.format(
"Only one of '%1$scredentials.jwt.key', '%1$scredentials.jwt.key-file'"
+ " or '%1$scredentials.jwt.key-store-file' can be configured",
configPrefix));
}
boolean jwtKeyConfigured = jwtKeyPropsCount == 1;
boolean jwtBearerOrSpiffe = creds.jwt().source() == Source.BEARER
|| creds.jwt().source() == Source.SPIFFE_JWT;
if (jwtSecretConfigured && jwtKeyConfigured) {
throw new ConfigurationException(
String.format(
"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",
configPrefix));
}
if (clientSecretConfigured && jwtKeyConfigured) {
throw new ConfigurationException(
String.format(
"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",
configPrefix));
}
if (clientSecretConfigured && jwtBearerOrSpiffe) {
throw new ConfigurationException(
String.format(
"Only one of client secret or JWT bearer/SPIFFE authentication methods can be configured,"
+ " but '%1$scredentials' has both a client secret and '%1$scredentials.jwt.source=%2$s' set",
configPrefix, creds.jwt().source().toString().toLowerCase()));
}
if (jwtKeyConfigured && jwtBearerOrSpiffe) {
throw new ConfigurationException(
String.format(
"Only one of JWT private key or JWT bearer/SPIFFE authentication methods can be configured,"
+ " but '%1$scredentials' has both a JWT key property and '%1$scredentials.jwt.source=%2$s' set",
configPrefix, creds.jwt().source().toString().toLowerCase()));View on GitHub (pinned to e1c734241f)
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
Example fix
# before quarkus.oidc-client.credentials.client-secret.value=secret123 quarkus.oidc-client.credentials.jwt.key-file=/etc/certs/key.pem # after quarkus.oidc-client.credentials.jwt.key-file=/etc/certs/key.pem
Defensive patterns
Strategy: validation
Validate before calling
boolean clientSecret = ConfigProvider.getConfig().getOptionalValue("quarkus.oidc-client.credentials.client-secret.value", String.class).isPresent();
boolean jwtKey = ConfigProvider.getConfig().getOptionalValue("quarkus.oidc-client.credentials.jwt.key-file", String.class).isPresent();
if (clientSecret && jwtKey) throw new IllegalStateException("Use either a client secret or a JWT private key"); Try / catch
try {
start();
} catch (ConfigurationException e) {
if (e.getMessage().contains("both a client secret and a JWT key")) log.error("Drop the client-secret or the jwt.key property");
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The '%s' property can only be set to 'idtoken' for WEB_APP a
- '%s' must be enabled to use '%s'
- UserInfo is required but DefaultTokenStateManager is configu
- Access token is required to check the roles but DefaultToken
- UserInfo path is missing but 'verifyAccessTokenWithUserInfo'
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b65781e4313c1d11.
Report an issue: GitHub.