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

  1. Remove the credentials.jwt.* properties if you want plain client-secret authentication
  2. Remove credentials.secret / credentials.client-secret.* if you intend to authenticate with a signed JWT secret
  3. 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

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

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/fe4511f15d0f2fe6. Report an issue: GitHub.