quarkusio/quarkus · error · ConfigurationException
UserInfo is required but DefaultTokenStateManager is…
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.
Solutions
- Set quarkus.oidc.token-state-manager.strategy=keep-all-tokens so the access token is retained
- Remove the requirement: set authentication.user-info-required=false and roles.source away from userinfo
- 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
- Treat token-state-manager.strategy changes as breaking UserInfo features
- Prefer keep-all-tokens unless cookie size is a proven problem
- Test UserInfo flows after changing strategy
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
- UserInfo path is missing but…
- '%1$scredentials.jwt.source' is set to 'spiffe-jwt', but no…
- Access token is required to check the roles but…
- Authorization code flow access token which is required to…
- Cannot find the Proxy registry configuration
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/150b5f52718f4581.
Report an issue: GitHub.
Appendix: 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)