{"record":{"id":"db52a7a4feceec9f","repo":"quarkusio/quarkus","slug":"currently-only-service-applications-can-be-used","errorCode":null,"errorMessage":"Currently only 'service' applications can be used to verify tokens with inlined certificate chains","messagePattern":"Currently only 'service' applications can be used to verify tokens with inlined certificate chains","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java","lineNumber":403,"sourceCode":"        } else {\n            oidcConfig.authentication.setUserInfoRequired(true);\n        }\n        return true;\n    }\n\n    private Uni<TenantConfigContext> createTenantContextFromPublicKey(OidcTenantConfig oidcConfig) {\n        if (!OidcUtils.isServiceApp(oidcConfig)) {\n            throw new ConfigurationException(\"'public-key' property can only be used with the 'service' applications\");\n        }\n        LOG.debug(\"'public-key' property for the local token verification is set,\"\n                + \" no connection to the OIDC server will be created\");\n\n        return TenantConfigContext.createReady(new OidcProvider(oidcConfig.publicKey().get(), oidcConfig), oidcConfig);\n    }\n\n    private Uni<TenantConfigContext> createTenantContextToVerifyCertChain(OidcTenantConfig oidcConfig) {\n        if (!OidcUtils.isServiceApp(oidcConfig)) {\n            throw new ConfigurationException(\n                    \"Currently only 'service' applications can be used to verify tokens with inlined certificate chains\");\n        }\n\n        return TenantConfigContext.createReady(new OidcProvider(null, oidcConfig), oidcConfig);\n    }\n\n    private OIDCException toOidcException(Throwable cause, String authServerUrl, String tenantId) {\n        final String message = OidcCommonUtils.formatConnectionErrorMessage(authServerUrl);\n        LOG.warn(message);\n        fireOidcServerNotAvailableEvent(authServerUrl, tenantId);\n        return new OIDCException(\"OIDC Server is not available\", cause);\n    }\n\n    private Uni<OidcProvider> createOidcProvider(OidcTenantConfig oidcConfig) {\n        return createOidcClientUni(oidcConfig)\n                .flatMap(new Function<OidcProviderClientImpl, Uni<? extends OidcProvider>>() {\n                    @Override\n                    public Uni<OidcProvider> apply(OidcProviderClientImpl client) {","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantContextFactory.java#L385-L421","documentation":"Quarkus OIDC throws this when a tenant is configured to verify tokens whose certificate chains are inlined (e.g. 'certificate-chain' public key verification), but the tenant is not a 'service' application. Certificate-chain verification is only implemented for bearer-token service apps without an OIDC server; web-app/code-flow tenants are rejected at tenant context creation time during startup.","triggerScenarios":"An OidcTenantConfig sets a certificate-chain based token verification (e.g. quarkus.oidc.token-path or public-key verification via inlined certs / tls certificate-chain) while the tenant also configures an auth-server-url / code flow, making OidcUtils.isServiceApp(oidcConfig) return false when createTenantContextToVerifyCertChain runs.","commonSituations":"Copying a service-app config into a web-app tenant; mixing token verification via inlined certificates with authorization-code-flow configuration; setting verification strategy to 'certificate' on a tenant with authentication.request or code-flow settings.","solutions":["Make the tenant a pure 'service' application: remove auth-server-url / code-flow settings so OidcUtils.isServiceApp returns true (application-type=service, no authentication mechanism redirection).","Switch token verification to a different strategy (e.g. verify with the OIDC server via jwks) if the tenant must remain a web-app.","If you truly need certificate-chain verification for a web-app tenant, split it into a separate service-type tenant configured with quarkus.oidc.tenant-<name>.application-type=service."],"exampleFix":"// before\nquarkus.oidc.tenant-b.auth-server-url=https://idp.example.com\nquarkus.oidc.tenant-b.certificate-chain-inline=true\n\n// after\nquarkus.oidc.tenant-b.application-type=service\n# remove auth-server-url so cert-chain verification is allowed","handlingStrategy":"validation","validationCode":"if (!\"service\".equals(oidcConfig.applicationType().orElse(\"service\")) && usesCertChainVerification(oidcConfig)) {\n    throw new IllegalStateException(\"certificate-chain verification requires a 'service' application-type tenant\");\n}","typeGuard":"boolean isServiceAppTenant(OidcTenantConfig cfg) {\n    return cfg.authServerUrl().isEmpty() && !cfg.token().isUserinfoRequired().orElse(false);\n}","tryCatchPattern":null,"preventionTips":["Keep cert-chain-inline tenants free of auth-server-url and code-flow settings.","Set application-type=service explicitly for certificate verification tenants.","Test tenant startup early — this fails during tenant context creation, not at request time."],"tags":["oidc","configuration","quarkus"],"backgroundTag":"oidc-tenant-misconfiguration","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"}