{"record":{"id":"e0e378514e1cf16a","repo":"quarkusio/quarkus","slug":"userinfo-is-not-required-but-userinfo-is-expected","errorCode":null,"errorMessage":"UserInfo is not required but UserInfo is expected to be the source of authorization roles","messagePattern":"UserInfo is not required but UserInfo is expected to be the source of authorization roles","errorType":"validation","errorClass":"io.quarkus.runtime.configuration.ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":216,"sourceCode":"                                + \" because either 'TenantConfigResolver' which will resolve tenant configurations is registered\"\n                                + \" or named tenants are configured.\");\n                        oidcConfig.tenantEnabled = false;\n                        return TenantConfigContext.createReady(new OidcProvider(null, null, null), oidcConfig);\n                    }\n                }\n                throw new ConfigurationException(\n                        \"'\" + getConfigPropertyForTenant(tenantId, \"auth-server-url\") + \"' property must be configured\");\n            }\n            OidcCommonUtils.verifyEndpointUrl(oidcConfig.authServerUrl().get());\n            OidcCommonUtils.verifyCommonConfiguration(oidcConfig, OidcUtils.isServiceApp(oidcConfig), true);\n            verifyAllowedRoutes(oidcConfig, tenantId);\n        } catch (ConfigurationException t) {\n            return Uni.createFrom().failure(t);\n        }\n\n        if (oidcConfig.roles().source().orElse(null) == io.quarkus.oidc.runtime.OidcTenantConfig.Roles.Source.userinfo\n                && !enableUserInfo(oidcConfig)) {\n            throw new ConfigurationException(\n                    \"UserInfo is not required but UserInfo is expected to be the source of authorization roles\");\n        }\n        if (oidcConfig.token().verifyAccessTokenWithUserInfo().orElse(false) && !OidcUtils.isWebApp(oidcConfig)\n                && !enableUserInfo(oidcConfig)) {\n            String propertyName = getConfigPropertyForTenant(tenantId, \"token.verify-access-token-with-user-info\");\n            throw new ConfigurationException(\"UserInfo is not required but '%s' is enabled\".formatted(propertyName));\n        }\n        if (!oidcConfig.authentication().idTokenRequired().orElse(true) && OidcUtils.isWebApp(oidcConfig)\n                && StepUpAuthenticationPolicy.isEnabled()) {\n            String propertyName = getConfigPropertyForTenant(tenantId, \"authentication.id-token-required\");\n            // this can be false alarm in case Quarkus application have multiple tenants and 'acr' values are not\n            // required for this tenant, which we cannot know\n            LOG.warnf(\"Step Up Authentication is not supported for tenant '%s', because the internal IdToken is\"\n                    + \" generated by Quarkus. Please see the '%s' configuration property documentation for more information\",\n                    tenantId, propertyName);\n        }\n        if (!oidcConfig.authentication().idTokenRequired().orElse(true) && !enableUserInfo(oidcConfig)\n                && oidcConfig.token().verifyAccessTokenWithUserInfo().orElse(false)) {","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L198-L234","documentation":"A tenant configured roles.source=userinfo asks Quarkus to load authorization roles from the IdP's UserInfo endpoint. But UserInfo is only fetched when it is marked required (authentication.userInfoRequired=true or appropriate app type). createTenantContext detects the contradiction — UserInfo is the roles source yet never required — and throws this ConfigurationException.","triggerScenarios":"createTenantContext sees oidcConfig.roles().source() == Roles.Source.userinfo while enableUserInfo(oidcConfig) returns false — e.g. quarkus.oidc.roles.source=userinfo set without quarkus.oidc.authentication.user-info-required=true (and the tenant is not a web-app that implies UserInfo).","commonSituations":"Copy-pasting a roles.source=userinfo snippet without the matching user-info-required setting; changing application-type to service while keeping userinfo roles source; overriding user-info-required to false in a profile while roles.source stays userinfo.","solutions":["Set quarkus.oidc.authentication.user-info-required=true (tenant-scoped variant for named tenants).","Or remove/change quarkus.oidc.roles.source if roles should come from the ID token/access token instead.","Or switch the tenant's application-type to web-app where UserInfo requirement is derived automatically if that is the intent."],"exampleFix":"// before\nquarkus.oidc.roles.source=userinfo\n\n// after\nquarkus.oidc.roles.source=userinfo\nquarkus.oidc.authentication.user-info-required=true","handlingStrategy":"validation","validationCode":"if (\"userinfo\".equals(config.getProperty(\"quarkus.oidc.roles.source\"))\n        && !\"true\".equals(config.getProperty(\"quarkus.oidc.authentication.user-info-required\"))) {\n    throw new IllegalStateException(\"roles.source=userinfo requires authentication.user-info-required=true\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat roles.source=userinfo and user-info-required=true as an inseparable pair.","Review config when changing application-type, since UserInfo requirement may become implicit or lost.","Search profiles/overrides for settings that disable user-info-required."],"tags":["oidc","configuration","userinfo","roles","startup"],"backgroundTag":"inconsistent-oidc-userinfo-config","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"}