---
title: "Configure Identity Provider"
description: "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."
stack: "Enterprise Stack (commercial) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/administration/access-and-permissions/external-role-mapping/configure-idp
generated: 2026-07-20
---
# 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:

| Field | Value |
|-------|-------|
| Name | `realm-roles` |
| Token Claim Name | `realm_access.roles` |
| Add to ID token | **ON** |
| Add to access token | **ON** |

### Step 3: Verify Token

After login, the ID token should contain:

```json
{
  "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:

```json
{
  "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):

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

**Info:**

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:

```json
{
  "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.

### Using Actions (Recommended)

1. Go to **Actions → Flows → Login**
2. Add a custom action:

```javascript
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);
};
```

3. Assign roles in user `app_metadata`:

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

Token includes:

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

**Error:**

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](https://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

```bash
# 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:

```hocon
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

| Field | Default | Description |
|-------|---------|-------------|
| `enabled` | `false` | Extract 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 |

**Info:**

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

## Next Steps

- [Create Mappings](https://docs.walt.id/enterprise-stack/administration/access-and-permissions/external-role-mapping/create-mappings.md) — Map external roles to Enterprise roles
