quarkusio/quarkus · error · ConfigurationException

UserInfo is required but DefaultTokenStateManager is configu

Error message

UserInfo is required but DefaultTokenStateManager is configured to not keep the access token

What it means

The DefaultTokenStateManager stores tokens in the encrypted session cookie; with the default strategy it does not keep the access token. If UserInfo is required (or roles come from userinfo) the access token is needed to call the UserInfo endpoint, so Quarkus fails the tenant context with this ConfigurationException.

Source

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

                        "Session age extension will not be effective because 'quarkus.oidc.token.refresh-expired=true' is not set");
            }
            if (!oidcConfig.token().refreshExpired()
                    && !oidcConfig.token().refreshTokenCacheTimeToLive().isZero()) {
                throw new ConfigurationException(
                        "'" + getConfigPropertyForTenant(tenantId, "token.refresh-expired")
                                + "' must be enabled to use '"
                                + getConfigPropertyForTenant(tenantId, "token.refresh-token-cache-time-to-live")
                                + "'");
            }
        }

        if (oidcConfig.tokenStateManager()
                .strategy() != io.quarkus.oidc.runtime.OidcTenantConfig.TokenStateManager.Strategy.KEEP_ALL_TOKENS) {

            if (oidcConfig.authentication().userInfoRequired().orElse(false)
                    || oidcConfig.roles().source()
                            .orElse(null) == io.quarkus.oidc.runtime.OidcTenantConfig.Roles.Source.userinfo) {
                throw new ConfigurationException(
                        "UserInfo is required but DefaultTokenStateManager is configured to not keep the access token");
            }
            if (oidcConfig.roles().source().orElse(null) == io.quarkus.oidc.runtime.OidcTenantConfig.Roles.Source.accesstoken) {
                throw new ConfigurationException(
                        "Access token is required to check the roles but DefaultTokenStateManager is configured to not keep the access token");
            }
        }

        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");
                }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set quarkus.oidc.token-state-manager.strategy=keep-all-tokens so the access token is retained
  2. Remove the requirement: set authentication.user-info-required=false and roles.source away from userinfo
  3. Use a custom TokenStateManager if session-cookie size is the concern, while still persisting the access token

Example fix

// before
quarkus.oidc.authentication.user-info-required=true
quarkus.oidc.token-state-manager.strategy=keep-id-token
// after
quarkus.oidc.authentication.user-info-required=true
quarkus.oidc.token-state-manager.strategy=keep-all-tokens
Defensive patterns

Strategy: validation

Validate before calling

boolean keepsAccessToken = config.tokenStateManager().strategy() == TokenStateManager.Strategy.KEEP_ALL_TOKENS;
if (!keepsAccessToken && (config.authentication().userInfoRequired().orElse(false)
        || config.roles().source().orElse(null) == Roles.Source.userinfo)) {
    throw new IllegalArgumentException("strategy must be keep-all-tokens when UserInfo is required");
}

Type guard

boolean keepsAccessToken(OidcTenantConfig c) {
    return c.tokenStateManager().strategy() == OidcTenantConfig.TokenStateManager.Strategy.KEEP_ALL_TOKENS;
}

Prevention

When it happens

Trigger: tokenStateManager().strategy() != KEEP_ALL_TOKENS while authentication().userInfoRequired()=true or roles().source()==userinfo, at createTenantContext time.

Common situations: Customizing quarkus.oidc.token-state-manager.strategy (e.g. keep-id-token or state-only) while still requiring UserInfo or userinfo-based roles; tightening the cookie size by dropping the access token then hitting UserInfo requirements.

Related errors


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