quarkusio/quarkus · error · OIDCException

OidcConfigurationMetadata can not be injected

Error message

OidcConfigurationMetadata can not be injected

What it means

OidcConfigurationAndProviderProducer.produceMetadata() @Produces OidcConfigurationMetadata from the SecurityIdentity's CONFIG_METADATA_ATTRIBUTE, falling back to the default tenant's provider metadata. If neither is available, injection fails with OIDCException - the metadata is only present after successful authentication by the default (or identity-carrying) tenant.

Source

Thrown at extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationAndProviderProducer.java:28

import io.quarkus.security.identity.SecurityIdentity;

@RequestScoped
public class OidcConfigurationAndProviderProducer {
    @Inject
    TenantConfigBean tenantConfig;
    @Inject
    SecurityIdentity identity;

    @Produces
    @RequestScoped
    OidcConfigurationMetadata produceMetadata() {
        OidcConfigurationMetadata configMetadata = OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE);

        if (configMetadata == null && tenantConfig.getDefaultTenant().oidcConfig().tenantEnabled()) {
            configMetadata = tenantConfig.getDefaultTenant().provider().getMetadata();
        }
        if (configMetadata == null) {
            throw new OIDCException("OidcConfigurationMetadata can not be injected");
        }
        return configMetadata;
    }

    @Produces
    @RequestScoped
    OidcProviderClient produceProviderClient() {
        OidcProviderClient client = null;
        String tenantId = OidcUtils.getAttribute(identity, OidcUtils.TENANT_ID_ATTRIBUTE);
        if (tenantId != null) {
            if (OidcUtils.DEFAULT_TENANT_ID.equals(tenantId)) {
                return tenantConfig.getDefaultTenant().getOidcProviderClient();
            }
            TenantConfigContext context = tenantConfig.getStaticTenant(tenantId);
            if (context == null) {
                context = tenantConfig.getDynamicTenant(tenantId);
            }
            if (context != null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Enable the default tenant (quarkus.oidc.tenant-enabled=true) if your app actually authenticates against the default provider.
  2. Don't inject OidcConfigurationMetadata directly; instead obtain metadata from the TenantConfigContext/provider for the tenant you care about, or read it from the SecurityIdentity attribute yourself with a null check.
  3. Ensure injection happens only within an authenticated request (RequestScoped) and not during startup or scheduled tasks.

Example fix

// before
@Inject OidcConfigurationMetadata metadata; // fails when default tenant disabled

// after - fetch from the specific tenant's provider
@Inject TenantConfigBean tenantConfig;
OidcConfigurationMetadata metadata =
    tenantConfig.getStaticTenant("my-tenant").getOidcProviderClient().getMetadata();
Defensive patterns

Strategy: try-catch

Validate before calling

boolean canInjectMetadata = OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE) != null
    || tenantConfig.getDefaultTenant().oidcConfig().tenantEnabled();

Type guard

boolean hasMetadata(SecurityIdentity identity, TenantConfigBean cfg) {
    return OidcUtils.getAttribute(identity, OidcUtils.CONFIG_METADATA_ATTRIBUTE) != null
        || cfg.getDefaultTenant().oidcConfig().tenantEnabled();
}

Try / catch

try {
    return metadataService.call();
} catch (OIDCException e) {
    if (e.getMessage().contains("OidcConfigurationMetadata")) {
        // resolve metadata from the specific tenant provider instead
    }
    throw e;
}

Prevention

When it happens

Trigger: Inject OidcConfigurationMetadata in a bean during a request where the SecurityIdentity has no CONFIG_METADATA_ATTRIBUTE and either the default tenant is disabled (quarkus.oidc.tenant-enabled=false) or the identity was produced by a non-default/dynamic tenant without that attribute.

Common situations: Injecting OidcConfigurationMetadata in apps using only named tenants or TenantConfigResolver-based dynamic tenants with the default tenant disabled; using the injection outside authenticated request scope (e.g. startup, background thread).

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/fe2d864fc3a2ce0e. Report an issue: GitHub.