{"record":{"id":"79ab12f6161d13bf","repo":"quarkusio/quarkus","slug":"access-token-is-required-to-check-the-roles-but-de","errorCode":null,"errorMessage":"Access token is required to check the roles but DefaultTokenStateManager is configured to not keep the access token","messagePattern":"Access token is required to check the roles but DefaultTokenStateManager is configured to not keep the access token","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":328,"sourceCode":"                throw new ConfigurationException(\n                        \"'\" + getConfigPropertyForTenant(tenantId, \"token.refresh-expired\")\n                                + \"' must be enabled to use '\"\n                                + getConfigPropertyForTenant(tenantId, \"token.refresh-token-cache-time-to-live\")\n                                + \"'\");\n            }\n        }\n\n        if (oidcConfig.tokenStateManager()\n                .strategy() != io.quarkus.oidc.runtime.OidcTenantConfig.TokenStateManager.Strategy.KEEP_ALL_TOKENS) {\n\n            if (oidcConfig.authentication().userInfoRequired().orElse(false)\n                    || oidcConfig.roles().source()\n                            .orElse(null) == io.quarkus.oidc.runtime.OidcTenantConfig.Roles.Source.userinfo) {\n                throw new ConfigurationException(\n                        \"UserInfo is required but DefaultTokenStateManager is configured to not keep the access token\");\n            }\n            if (oidcConfig.roles().source().orElse(null) == io.quarkus.oidc.runtime.OidcTenantConfig.Roles.Source.accesstoken) {\n                throw new ConfigurationException(\n                        \"Access token is required to check the roles but DefaultTokenStateManager is configured to not keep the access token\");\n            }\n        }\n\n        if (oidcConfig.token().verifyAccessTokenWithUserInfo().orElse(false)) {\n            if (!oidcConfig.discoveryEnabled().orElse(true)) {\n                if (oidcConfig.userInfoPath().isEmpty()) {\n                    throw new ConfigurationException(\n                            \"UserInfo path is missing but 'verifyAccessTokenWithUserInfo' is enabled\");\n                }\n                if (oidcConfig.introspectionPath().isPresent()) {\n                    throw new ConfigurationException(\n                            \"Introspection path is configured and 'verifyAccessTokenWithUserInfo' is enabled, these options are mutually exclusive\");\n                }\n            }\n        }\n\n        if (!oidcConfig.token().issuedAtRequired() && oidcConfig.token().age().isPresent()) {","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L310-L346","documentation":"When roles are configured to be read from the access token (roles.source=accesstoken), the access token must be available. The DefaultTokenStateManager with the default strategy does not store the access token, so Quarkus throws this ConfigurationException when creating the tenant context.","triggerScenarios":"tokenStateManager().strategy() != KEEP_ALL_TOKENS and roles().source() == Source.accesstoken during createTenantContext.","commonSituations":"Setting quarkus.oidc.roles.source=accesstoken in a web-app where the strategy drops the access token from the session cookie; combining a slim token-state-manager strategy with access-token role checks.","solutions":["Set quarkus.oidc.token-state-manager.strategy=keep-all-tokens","Change roles.source (e.g. idtoken for web-apps) if access-token roles are not required","Implement a custom TokenStateManager that persists the access token"],"exampleFix":"// before\nquarkus.oidc.roles.source=accesstoken\nquarkus.oidc.token-state-manager.strategy=keep-id-token\n// after\nquarkus.oidc.roles.source=accesstoken\nquarkus.oidc.token-state-manager.strategy=keep-all-tokens","handlingStrategy":"validation","validationCode":"if (config.roles().source().orElse(null) == Roles.Source.accesstoken\n        && config.tokenStateManager().strategy() != TokenStateManager.Strategy.KEEP_ALL_TOKENS) {\n    throw new IllegalArgumentException(\"strategy must be keep-all-tokens when roles.source=accesstoken\");\n}","typeGuard":"boolean needsAccessToken(OidcTenantConfig c) {\n    return c.roles().source().orElse(null) == OidcTenantConfig.Roles.Source.accesstoken;\n}","tryCatchPattern":null,"preventionTips":["Pair roles.source=accesstoken with strategy=keep-all-tokens","Add a startup config smoke test for tenant settings"],"tags":["quarkus","oidc","configuration","roles"],"backgroundTag":"oidc-token-state-strategy-conflict","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}