Conditional Mappings

Conditional mappings add restrictions to when an external role maps to an Enterprise role. This enables fine-grained control over permission assignment.

Use Cases

  • Email domain restrictions — Only map roles for users from specific domains
  • Provider restrictions — Only map roles from specific Identity Providers
  • Claim-based restrictions — Map based on additional token claims

Email Domain Conditions

Restrict a mapping to users with specific email domains:

CURL
Request Body
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": true,
    "conditions": {
      "emailDomains": ["company.com", "subsidiary.com"]
    }
  }'

With this mapping:

  • User alice@company.com with role admin → Gets BW_ADMIN
  • User bob@subsidiary.com with role admin → Gets BW_ADMIN
  • User eve@contractor.io with role adminNo mapping (domain not allowed)

Provider Restrictions

Restrict a mapping to a specific Identity Provider:

curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "providerId": "keycloak-production"
  }'

With this mapping:

  • User logging in via keycloak-production with role admin → Gets BW_ADMIN
  • User logging in via azure-ad with role adminNo mapping

Use provider restrictions when you have the same role name across different IdPs but want different Enterprise mappings.

Combining Conditions

Combine multiple conditions — all must be met:

curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "providerId": "keycloak-production",
    "conditions": {
      "emailDomains": ["company.com"]
    }
  }'

This mapping applies only when:

  1. User authenticates via keycloak-production AND
  2. User's email ends with @company.com AND
  3. User has the admin role

Required Claims Conditions

Require specific claims in the token:

curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "conditions": {
      "requiredClaims": {
        "department": "engineering",
        "level": "senior"
      }
    }
  }'

The user's ID token must contain:

{
  "department": "engineering",
  "level": "senior"
}

Practical Examples

Example 1: Partner Access

Allow partners to access a limited role, but only from their domain:

# Partners get BW_VIEWER, restricted to their domains
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_VIEWER/roles-api/roles/external-mappings/partner' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "conditions": {
      "emailDomains": ["partner1.com", "partner2.com"]
    }
  }'

Example 2: Multi-Provider Setup

Different IdPs map the same external role to different Enterprise roles:

# Keycloak 'admin' → Full admin
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "providerId": "keycloak"
  }'

# Azure AD 'admin' → Limited admin
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_LIMITED_ADMIN/roles-api/roles/external-mappings/admin' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "providerId": "azure-ad"
  }'

Example 3: Contractor Restrictions

External contractors get access, but only during their contract period:

# Contractors with valid department claim
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.BW_CONTRACTOR/roles-api/roles/external-mappings/contractor' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "conditions": {
      "emailDomains": ["contractor-agency.com"],
      "requiredClaims": {
        "contract_status": "active"
      }
    }
  }'

Example 4: Department-Based Access

Map based on department from IdP:

# Engineering department → Developer role
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.DEVELOPER/roles-api/roles/external-mappings/employee' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "conditions": {
      "requiredClaims": {
        "department": "engineering"
      }
    }
  }'

# Finance department → Finance role
curl -X PUT \
  'https://{host}/v1/waltid.tenant1.FINANCE/roles-api/roles/external-mappings/employee' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "enabled": true,
    "conditions": {
      "requiredClaims": {
        "department": "finance"
      }
    }
  }'

Testing Conditional Mappings

Use the resolution endpoint to test conditions:

# Test with matching email domain
curl -X POST \
  'https://{host}/v1/waltid/roles-api/roles/external-mappings/resolve' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "externalRoles": ["admin"],
    "email": "user@company.com"
  }'

# Test with non-matching email domain
curl -X POST \
  'https://{host}/v1/waltid/roles-api/roles/external-mappings/resolve' \
  -H 'Authorization: Bearer {token}' \
  -d '{
    "externalRoles": ["admin"],
    "email": "user@other.com"
  }'

Condition Reference

ConditionTypeDescription
emailDomainsstringUser email must end with one of these domains
requiredClaimsobjectToken must contain these claim key-value pairs
providerIdstringMust authenticate via this specific provider

Best Practices

  1. Start simple — Add conditions only when needed
  2. Test thoroughly — Use resolution endpoint before deploying
  3. Document conditions — Keep track of why each condition exists
  4. Audit regularly — Review conditions to ensure they're still needed
  5. Fail securely — When in doubt, use stricter conditions
Last updated on May 7, 2026