quarkusio/quarkus · error · OIDCException

Application 'web-app' type is only supported if access token

Error message

Application 'web-app' type is only supported if access token is the source of roles

What it means

KeycloakPolicyEnforcerUtil.createPolicyEnforcer rejects OidcTenantConfig whose applicationType is web-app unless the role source is the access token. The policy enforcer relies on claims from the access token to make authorization decisions, so role sources like idtoken or userinfo are incompatible with web-app type.

Source

Thrown at extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/KeycloakPolicyEnforcerUtil.java:41

import io.quarkus.proxy.ProxyConfiguration;
import io.quarkus.proxy.ProxyConfigurationRegistry;
import io.quarkus.runtime.configuration.ConfigurationException;

public final class KeycloakPolicyEnforcerUtil {

    private KeycloakPolicyEnforcerUtil() {
        // UTIL CLASS
    }

    static PolicyEnforcer createPolicyEnforcer(OidcTenantConfig oidcConfig,
            KeycloakPolicyEnforcerTenantConfig keycloakPolicyEnforcerConfig,
            TlsConfigSupport tlsConfigSupport,
            ProxyConfigurationRegistry proxyConfigurationRegistry) {

        if (oidcConfig.applicationType()
                .orElse(OidcTenantConfig.ApplicationType.SERVICE) == OidcTenantConfig.ApplicationType.WEB_APP
                && oidcConfig.roles().source().orElse(null) != OidcTenantConfig.Roles.Source.accesstoken) {
            throw new OIDCException("Application 'web-app' type is only supported if access token is the source of roles");
        }

        AdapterConfig adapterConfig = new AdapterConfig();
        String authServerUrl = oidcConfig.authServerUrl().get();

        try {
            adapterConfig.setRealm(authServerUrl.substring(authServerUrl.lastIndexOf('/') + 1));
            adapterConfig.setAuthServerUrl(authServerUrl.substring(0, authServerUrl.lastIndexOf("/realms")));
        } catch (Exception cause) {
            throw new ConfigurationException("Failed to parse the realm name.", cause);
        }

        adapterConfig.setResource(oidcConfig.clientId().get());
        adapterConfig.setCredentials(getCredentials(oidcConfig));

        if (!tlsConfigSupport.useTlsRegistry()) {
            if (tlsConfigSupport.isGlobalTrustAll()) {
                adapterConfig.setDisableTrustManager(true);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set quarkus.oidc.roles.source=accesstoken so roles come from the access token.
  2. Or change quarkus.oidc.application-type=service if the app does not need web-app behavior.
  3. Remove conflicting roles.source configuration (leave default) when using the policy enforcer with web-app type.

Example fix

// before
quarkus.oidc.application-type=web-app
quarkus.oidc.roles.source=userinfo
// after
quarkus.oidc.application-type=web-app
quarkus.oidc.roles.source=accesstoken
Defensive patterns

Strategy: validation

Validate before calling

// fail fast at startup if config is incompatible
OidcTenantConfig c = /* resolved tenant config */;
boolean webApp = c.applicationType().orElse(OidcTenantConfig.ApplicationType.SERVICE)
        == OidcTenantConfig.ApplicationType.WEB_APP;
boolean badSource = c.roles().source().isPresent()
        && c.roles().source().get() != OidcTenantConfig.Roles.Source.accesstoken;
if (webApp && badSource) throw new IllegalStateException("Set roles.source=accesstoken for web-app + policy enforcer");

Try / catch

try {
    policyEnforcer = KeycloakPolicyEnforcerUtil.createPolicyEnforcer(...);
} catch (OIDCException e) {
    if (e.getMessage().contains("access token is the source of roles")) {
        log.error("Set quarkus.oidc.roles.source=accesstoken or application-type=service");
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring quarkus.oidc.application-type=web-app (or leaving tenant config resolving to WEB_APP) together with quarkus.oidc.roles.source=user-id-token or =userinfo (or any source other than accesstoken) while the policy enforcer is enabled.

Common situations: Copying OIDC web-app role config (roles.source=userinfo) into an application that also enables quarkus.keycloak.policy-enforcer.enabled=true; switching an app from service to web-app type without revisiting role source.

Related errors


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