quarkusio/quarkus · error · ConfigurationException
Only one of client secret or JWT secret authentication metho
Error message
Only one of client secret or JWT secret authentication methods can be configured, but '%1$scredentials' has both a client secret and a JWT secret property set
What it means
verifyCommonConfiguration detects when both a client secret (credentials.secret / credentials.client-secret) and a JWT secret (credentials.jwt.secret / credentials.jwt.secret-provider) are configured. Client-secret (client_secret_basic/client_secret_post style) and JWT-secret (HMAC-signed JWT assertion) authentication are alternative methods, so having both set is ambiguous and rejected with a ConfigurationException.
Source
Thrown at extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java:188
throw new ConfigurationException(
String.format("'%sclient-id' property must be configured", configPrefix));
}
Credentials creds = oidcConfig.credentials();
if (creds.secret().isPresent() && creds.clientSecret().value().isPresent()) {
throw new ConfigurationException(
String.format(
"'%1$scredentials.secret' and '%1$scredentials.client-secret' properties are mutually exclusive",
configPrefix));
}
boolean clientSecretConfigured = creds.secret().isPresent()
|| creds.clientSecret().value().isPresent()
|| creds.clientSecret().provider().key().isPresent();
boolean jwtSecretConfigured = creds.jwt().secret().isPresent()
|| creds.jwt().secretProvider().key().isPresent();
if (clientSecretConfigured && jwtSecretConfigured) {
throw new ConfigurationException(
String.format(
"Only one of client secret or JWT secret authentication methods can be configured,"
+ " but '%1$scredentials' has both a client secret and a JWT secret property set",
configPrefix));
}
int jwtKeyPropsCount = (creds.jwt().key().isPresent() ? 1 : 0)
+ (creds.jwt().keyFile().isPresent() ? 1 : 0)
+ (creds.jwt().keyStoreFile().isPresent() ? 1 : 0);
if (jwtKeyPropsCount > 1) {
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;View on GitHub (pinned to e1c734241f)
Solutions
- Remove the credentials.jwt.* properties if you want plain client-secret authentication
- Remove credentials.secret / credentials.client-secret.* if you intend to authenticate with a signed JWT secret
- Decide one authentication method per client and document it to avoid future config drift
Example fix
// before quarkus.oidc.credentials.client-secret.value=topsecret quarkus.oidc.credentials.jwt.secret=jwtsigningkey // after quarkus.oidc.credentials.client-secret.value=topsecret
Defensive patterns
Strategy: validation
Validate before calling
boolean clientSecret = cfg.optional("quarkus.oidc.credentials.client-secret.value").isPresent()
|| cfg.optional("quarkus.oidc.credentials.secret").isPresent();
boolean jwtSecret = cfg.optional("quarkus.oidc.credentials.jwt.secret").isPresent();
if (clientSecret && jwtSecret) {
throw new IllegalArgumentException("Configure only one of client secret or JWT secret");
} Try / catch
try {
startApplication();
} catch (ConfigurationException e) {
if (e.getMessage().contains("JWT secret")) {
LOG.error("Remove either credentials.client-secret.* or credentials.jwt.secret");
}
} Prevention
- Pick one authentication method per OIDC client and stick to it
- Remove leftover jwt.secret config when switching to client-secret auth
- Review OIDC config diffs in code review for mixed credential styles
When it happens
Trigger: Startup with, for the same prefix, any of credentials.secret/client-secret.value/client-secret.provider set AND any of credentials.jwt.secret/jwt.secret-provider.key set.
Common situations: Copying credential blocks from examples for different auth styles; an old HMAC JWT config left in place after switching to client-secret auth; team members adding JWT auth on top of existing secret auth.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- ISSUED_AT_INVALID_PAST
- Cannot get token for tenant '%s' because a %s client_asserti
- '%1$scredentials.secret' and '%1$scredentials.client-secret'
- Only one of JWT secret or JWT private key authentication met
- Only one of client secret or JWT bearer/SPIFFE authenticatio
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fe4511f15d0f2fe6.
Report an issue: GitHub.