quarkusio/quarkus · error · ConfigurationException

The '%s' can only be set to false if '%s' is not set. Either

Error message

The '%s' can only be set to false if '%s' is not set. Either set '%s' to true or do not set '%s'.

What it means

Token age verification compares the token's issued-at (iat) claim against token.age. If token.issued-at-required=false the iat claim is not required, making age checks meaningless and error-prone; Quarkus therefore forbids setting issued-at-required=false while token.age is present, reporting both properties in the ConfigurationException.

Source

Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java:349

        }

        if (oidcConfig.token().verifyAccessTokenWithUserInfo().orElse(false)) {
            if (!oidcConfig.discoveryEnabled().orElse(true)) {
                if (oidcConfig.userInfoPath().isEmpty()) {
                    throw new ConfigurationException(
                            "UserInfo path is missing but 'verifyAccessTokenWithUserInfo' is enabled");
                }
                if (oidcConfig.introspectionPath().isPresent()) {
                    throw new ConfigurationException(
                            "Introspection path is configured and 'verifyAccessTokenWithUserInfo' is enabled, these options are mutually exclusive");
                }
            }
        }

        if (!oidcConfig.token().issuedAtRequired() && oidcConfig.token().age().isPresent()) {
            String tokenIssuedAtRequired = getConfigPropertyForTenant(tenantId, "token.issued-at-required");
            String tokenAge = getConfigPropertyForTenant(tenantId, "token.age");
            throw new ConfigurationException(
                    "The '" + tokenIssuedAtRequired + "' can only be set to false if '" + tokenAge + "' is not set." +
                            " Either set '" + tokenIssuedAtRequired + "' to true or do not set '" + tokenAge + "'.",
                    Set.of(tokenIssuedAtRequired, tokenAge));
        }

        return createOidcProvider(oidcConfig).flatMap(p -> TenantConfigContext.createReady(p, oidcConfig));
    }

    private void verifyAllowedRoutes(OidcTenantConfig oidcConfig, String tenantId) {
        if (!allowedRoutes.contains(OidcRoute.BACKCHANNEL_LOGOUT) && oidcConfig.logout().backchannel().path().isPresent()) {
            LOG.warnf("'%s' is configured but the 'backchannel-logout' route is not in"
                    + " 'quarkus.oidc.allowed-routes'; this tenant will not support back-channel logout",
                    getConfigPropertyForTenant(tenantId, "logout.backchannel.path"), tenantId);
        }
        if (!allowedRoutes.contains(OidcRoute.RESOURCE_METADATA) && oidcConfig.resourceMetadata().enabled()) {
            LOG.warnf("'%s' is enabled but the 'resource-metadata' route is not in"
                    + " 'quarkus.oidc.allowed-routes'; this tenant will not provide protected resource metadata",
                    getConfigPropertyForTenant(tenantId, "resource-metadata.enabled"), tenantId);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set quarkus.oidc.token.issued-at-required=true so age verification can rely on iat
  2. Remove quarkus.oidc.token.age if iat cannot be guaranteed and age checks are not needed
  3. Check per-tenant overrides (quarkus.oidc.<tenant>.token.*) for the conflicting pair

Example fix

// before
quarkus.oidc.token.issued-at-required=false
quarkus.oidc.token.age=5M
// after
quarkus.oidc.token.issued-at-required=true
quarkus.oidc.token.age=5M
Defensive patterns

Strategy: validation

Validate before calling

if (!config.token().issuedAtRequired() && config.token().age().isPresent()) {
    throw new IllegalArgumentException("token.age requires token.issued-at-required=true");
}

Prevention

When it happens

Trigger: token().issuedAtRequired() is false and token().age().isPresent() during createTenantContext; the exception carries a set of the two offending property names.

Common situations: Setting quarkus.oidc.token.issued-at-required=false to tolerate tokens without iat while also configuring token.age; provider issuing tokens without iat leads to conflicting tuning.

Related errors


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