Configure Identity Provider

Before creating external role mappings, your Identity Provider (IdP) must be configured to include roles in the ID token. This page covers configuration for common providers.

Requirements

For external role mapping to work, your IdP must:

  1. Include roles in the ID token — Not just the access token
  2. Use a consistent claim path — Enterprise Stack must know where to find the roles
  3. Issue roles as an array — Even for single roles

Keycloak

Keycloak includes realm roles by default, but you need to ensure they appear in the ID token.

Step 1: Create Realm Roles

  1. Go to Realm roles in your realm
  2. Create roles: tenant-admin, wallet-operator, etc.
  3. Assign roles to users via Users → Role mapping

Step 2: Configure Client Mappers

Keycloak 26.x requires explicit mappers to include roles in tokens:

  1. Go to Clients → your-client → Client scopes
  2. Click on the dedicated scope (e.g., your-client-dedicated)
  3. Go to Mappers → Add mapper → By configuration
  4. Select User Realm Role
  5. Configure:
FieldValue
Namerealm-roles
Token Claim Namerealm_access.roles
Add to ID tokenON
Add to access tokenON

Step 3: Verify Token

After login, the ID token should contain:

{
  "realm_access": {
    "roles": ["tenant-admin", "wallet-operator"]
  }
}

Microsoft Entra ID (Azure AD)

Option A: App Roles

  1. Go to App registrations → your-app → App roles
  2. Create app roles: TenantAdmin, WalletOperator
  3. Assign roles via Enterprise applications → Users and groups

Roles appear in the roles claim:

{
  "roles": ["TenantAdmin", "WalletOperator"]
}

Option B: Security Groups

  1. Go to App registrations → your-app → Token configuration
  2. Add groups claim
  3. Select Security groups

Groups appear in the groups claim (as GUIDs or names depending on configuration):

{
  "groups": ["group-guid-1", "group-guid-2"]
}

When using groups, map the group identifier (GUID or name) as the external role in your mappings.

Okta

Step 1: Create Groups

  1. Go to Directory → Groups
  2. Create groups: TenantAdmins, WalletOperators
  3. Add users to groups

Step 2: Configure Groups Claim

  1. Go to Applications → your-app → Sign On
  2. Edit OpenID Connect ID Token
  3. Add Groups claim:
    • Claim name: groups
    • Filter: Matches regex .* (or specific pattern)
    • Include in: ID Token

Token includes:

{
  "groups": ["TenantAdmins", "WalletOperators"]
}

Alternative: Custom Claims

Use Okta Expression Language for custom role claims:

  1. Go to Security → API → Authorization Servers
  2. Select your server → Claims
  3. Add claim:
    • Name: roles
    • Value: Arrays.flatten(getFilteredGroups({"TenantAdmins", "WalletOperators"}, "group.name", 10))
    • Include in: ID Token

Auth0

Auth0 requires a Rule or Action to add roles to tokens.

  1. Go to Actions → Flows → Login
  2. Add a custom action:
exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://your-app.com/';
  
  // Get user's roles from metadata or app_metadata
  const roles = event.user.app_metadata?.roles || [];
  
  // Add to ID token
  api.idToken.setCustomClaim(namespace + 'roles', roles);
};
  1. Assign roles in user app_metadata:
{
  "roles": ["tenant-admin", "wallet-operator"]
}

Token includes:

{
  "https://your-app.com/roles": ["tenant-admin", "wallet-operator"]
}

Auth0 requires namespaced custom claims. Configure Enterprise Stack to use the full claim path.

Google Workspace

Google Workspace doesn't natively support roles in OIDC tokens. Options:

  1. Use Google Groups — Map group membership via directory API
  2. Custom attributes — Use admin-defined custom attributes
  3. External service — Use a token exchange or enrichment service

Generic OIDC Provider

For any OIDC provider:

  1. Check documentation for how to include custom claims in ID tokens
  2. Create roles/groups in the provider
  3. Configure claim mapping to include roles in ID token
  4. Note the claim path for Enterprise Stack configuration

Common claim paths:

  • roles — Simple array at top level
  • groups — Group membership
  • realm_access.roles — Keycloak style
  • resource_access.{client}.roles — Keycloak client roles
  • https://namespace/roles — Namespaced custom claims

Verify Token Contents

After configuring your IdP, verify the token contains roles:

Method 1: jwt.io

  1. Complete an OIDC login
  2. Capture the ID token
  3. Paste at jwt.io to decode

Method 2: Enterprise Demo App

  1. Login via OIDC in the Demo App
  2. Check "Realm Roles (from IdP)" in auth details

Method 3: Token Introspection

# Decode JWT payload
echo $ID_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | jq

Enterprise Stack Configuration

Enterprise Stack Configuration

Once your IdP is configured, tell Enterprise Stack where to find the roles.

In auth.conf, add externalRoleExtraction to your OIDC config:

authFlows = [
  {
    method = "oidc"
    config = {
      openIdConfigurationUrl = "https://your-idp/.well-known/openid-configuration"
      clientId = "your-client-id"
      clientSecret = "your-client-secret"
      callbackUri = "https://your-enterprise-host/auth/account/oidc/callback"
      pkceEnabled = true
      
      externalRoleExtraction = {
        enabled = true
        realmRolesClaimPath = "realm_access.roles"      # Adjust for your IdP
        clientRolesClaimPath = "resource_access"        # Optional
      }
    }
    success = true
  }
]

Configuration Fields

FieldDefaultDescription
enabledfalseExtract roles from OIDC tokens
realmRolesClaimPath"realm_access.roles"Path to realm/global roles
clientRolesClaimPath"resource_access"Path to client-specific roles
clientId(parent clientId)Which client's roles to extract

The clientId in externalRoleExtraction defaults to the parent config.clientId, so you don't need to specify it twice.

Next Steps

Last updated on May 7, 2026