{"record":{"id":"0c5172b98c304838","repo":"quarkusio/quarkus","slug":"userinfo-path-is-missing-but-verifyaccesstokenwit","errorCode":null,"errorMessage":"UserInfo path is missing but 'verifyAccessTokenWithUserInfo' is enabled","messagePattern":"UserInfo path is missing but 'verifyAccessTokenWithUserInfo' is enabled","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":336,"sourceCode":"        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()) {\n            String tokenIssuedAtRequired = getConfigPropertyForTenant(tenantId, \"token.issued-at-required\");\n            String tokenAge = getConfigPropertyForTenant(tenantId, \"token.age\");\n            throw new ConfigurationException(\n                    \"The '\" + tokenIssuedAtRequired + \"' can only be set to false if '\" + tokenAge + \"' is not set.\" +\n                            \" Either set '\" + tokenIssuedAtRequired + \"' to true or do not set '\" + tokenAge + \"'.\",\n                    Set.of(tokenIssuedAtRequired, tokenAge));\n        }\n","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L318-L354","documentation":"With discovery disabled, Quarkus cannot learn the UserInfo endpoint from the provider's metadata, so it must be configured explicitly. If token.verify-access-token-with-user-info=true but no userinfoPath is set, the tenant context creation fails with this ConfigurationException.","triggerScenarios":"verifyAccessTokenWithUserInfo().orElse(false) is true, discoveryEnabled().orElse(true) is false, and userInfoPath() is empty at createTenantContext.","commonSituations":"Hard-coded OIDC endpoints (discovery-enabled=false) without a userinfo-path; pointing at a provider that lacks well-known metadata; disabling discovery to avoid the startup discovery call.","solutions":["Add quarkus.oidc.user-info-path=/userinfo (matching the provider's actual endpoint)","Re-enable discovery (quarkus.oidc.discovery-enabled=true) so the path is fetched from metadata","Disable token.verify-access-token-with-user-info if UserInfo verification is not needed"],"exampleFix":"// before\nquarkus.oidc.discovery-enabled=false\nquarkus.oidc.token.verify-access-token-with-user-info=true\n// after\nquarkus.oidc.discovery-enabled=false\nquarkus.oidc.token.verify-access-token-with-user-info=true\nquarkus.oidc.user-info-path=/userinfo","handlingStrategy":"validation","validationCode":"if (config.token().verifyAccessTokenWithUserInfo().orElse(false) && !config.discoveryEnabled().orElse(true)\n        && config.userInfoPath().isEmpty()) {\n    throw new IllegalArgumentException(\"user-info-path must be set when discovery is disabled\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Whenever discovery-enabled=false, list all required paths (token, userinfo, jwks, introspection)","Prefer discovery unless the provider lacks well-known metadata"],"tags":["quarkus","oidc","configuration","discovery","userinfo"],"backgroundTag":"oidc-discovery-disabled-missing-path","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}