{"record":{"id":"eb698ad4ebea25ad","repo":"quarkusio/quarkus","slug":"either-jwks-path-or-introspection-path-propert","errorCode":null,"errorMessage":"Either 'jwks-path' or 'introspection-path' properties must be set when the discovery is disabled.","messagePattern":"Either 'jwks-path' or 'introspection-path' properties must be set when the discovery is disabled\\.","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":258,"sourceCode":"        if (!oidcConfig.discoveryEnabled().orElse(true)) {\n            if (!OidcUtils.isServiceApp(oidcConfig)) {\n                if (oidcConfig.authorizationPath().isEmpty() || oidcConfig.tokenPath().isEmpty()) {\n                    String authorizationPathProperty = getConfigPropertyForTenant(tenantId, \"authorization-path\");\n                    String tokenPathProperty = getConfigPropertyForTenant(tenantId, \"token-path\");\n                    throw new ConfigurationException(\n                            \"'web-app' applications must have '\" + authorizationPathProperty + \"' and '\" + tokenPathProperty\n                                    + \"' properties \"\n                                    + \"set when the discovery is disabled.\",\n                            Set.of(authorizationPathProperty, tokenPathProperty));\n                }\n            }\n            // JWK and introspection endpoints have to be set for both 'web-app' and 'service' applications\n            if (oidcConfig.jwksPath().isEmpty() && oidcConfig.introspectionPath().isEmpty()) {\n                if (!oidcConfig.authentication().idTokenRequired().orElse(true)\n                        && oidcConfig.authentication().userInfoRequired().orElse(false)) {\n                    LOG.debugf(\"tenant %s supports only UserInfo\", oidcConfig.tenantId().get());\n                } else if (OidcUtils.isServiceApp(oidcConfig)) {\n                    throw new ConfigurationException(\n                            \"Either 'jwks-path' or 'introspection-path' properties must be set when the discovery is disabled.\",\n                            Set.of(\"quarkus.oidc.jwks-path\", \"quarkus.oidc.introspection-path\"));\n                }\n            }\n            if (oidcConfig.authentication().userInfoRequired().orElse(false) && oidcConfig.userInfoPath().isEmpty()) {\n                String configProperty = getConfigPropertyForTenant(tenantId, \"user-info-path\");\n                throw new ConfigurationException(\n                        \"UserInfo is required but '\" + configProperty + \"' is not configured.\",\n                        Set.of(configProperty));\n            }\n        }\n\n        if (OidcUtils.isServiceApp(oidcConfig)) {\n            if (oidcConfig.token().refreshExpired()) {\n                throw new ConfigurationException(\n                        \"The '\" + getConfigPropertyForTenant(tenantId, \"token.refresh-expired\")\n                                + \"' property can only be enabled for \"\n                                + io.quarkus.oidc.runtime.OidcTenantConfig.ApplicationType.WEB_APP","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L240-L276","documentation":"With discovery disabled, service (bearer token) applications must still be able to validate tokens — either by fetching signing keys from the JWKS endpoint or by introspecting the token at the provider. createTenantContext throws this ConfigurationException when discovery is off, neither jwks-path nor introspection-path is configured, and the tenant does not support only UserInfo.","triggerScenarios":"createTenantContext finds oidcConfig.discoveryEnabled() == false, both oidcConfig.jwksPath().isEmpty() and oidcConfig.introspectionPath().isEmpty(), and the tenant is a service app not configured with idTokenRequired=false + userInfoRequired=true (UserInfo-only tenants are exempted).","commonSituations":"Disabling discovery for a token-introspecting proxy setup but forgetting introspection-path; an IdP without the well-known endpoint where only the token endpoint was configured; copy-pasting a web-app tenant config (which only needs authorization/token paths) into a service app.","solutions":["Set quarkus.oidc.jwks-path (e.g. /protocol/openid-connect/certs) to verify JWTs locally.","Or set quarkus.oidc.introspection-path to verify tokens remotely via introspection.","Or re-enable discovery if the provider supports the well-known endpoint."],"exampleFix":"// before\nquarkus.oidc.discovery-enabled=false\n\n// after\nquarkus.oidc.discovery-enabled=false\nquarkus.oidc.jwks-path=/protocol/openid-connect/certs","handlingStrategy":"validation","validationCode":"if (\"false\".equals(config.getProperty(\"quarkus.oidc.discovery-enabled\"))\n        && config.getProperty(\"quarkus.oidc.jwks-path\") == null\n        && config.getProperty(\"quarkus.oidc.introspection-path\") == null) {\n    throw new IllegalStateException(\"Set jwks-path or introspection-path when discovery is disabled\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For service tenants with discovery off, always configure at least one token-validation path.","Decide up front between local JWKS validation and remote introspection and configure accordingly.","Re-verify paths when switching IdP versions or providers."],"tags":["oidc","configuration","discovery","jwks","introspection","startup"],"backgroundTag":"missing-required-config-property","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"}