> For the complete documentation index, see [llms.txt](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veza.com/4yItIzMvkpAvMVFAamTf/integrations/configuration/custom-identity-mappings.md).

# Custom Identity Mappings

Correlating identities across integrations when automatic matching does not apply

### Overview

Custom identity mappings define relationships between user identities and groups across the systems integrated with Veza. When your access federation does not produce these connections on its own, you can specify the attributes Veza compares to correlate identities between two systems, for example connecting an Okta user `tom.shaw@veza.com` to a SQL Server login `DOMAIN\tshaw`.

{% hint style="info" %}
Veza correlates many identities without any configuration. Read [Automatic Identity Matching](/4yItIzMvkpAvMVFAamTf/integrations/configuration/automatic-identity-matching.md) first: it lists the attributes Veza compares for each identity provider and the integrations that correlate on their own. A mapping that repeats what Veza already matches automatically produces no additional relationships.
{% endhint %}

Use custom identity mappings to:

* Connect identity provider users, such as Okta users, to local accounts, such as Trino users
* Connect identity provider groups to groups in downstream systems, such as an Active Directory group to an Okta group, or an Entra ID group to a GitHub team
* Correlate identities on an attribute Veza does not compare automatically, such as an employee ID, an email alias, or a custom property
* Define mapping rules for each integration, or use one rule to link identities or groups across multiple connected systems
* Correlate identities in a [custom identity provider](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/templates/custom-identity-provider-template.md) to those in another integrated provider such as Okta
* Map identity provider users to local users in a [custom application](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/templates/custom-application-template.md), as an alternative to setting [identity values](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/best-practices/cross-service-connections.md) in the payload
* Define access-granting relationships for any user or group that shares a name, email address, or other property in Access Graph
* Identify local account ownership using consistent naming patterns

### Cross-IdP risk coverage

When you use more than one identity provider, a single person exists as a separate identity in each one, and Access Graph holds a distinct user entity for every provider. For example, the same employee can appear as an Okta user, an Active Directory user, and an Azure AD user. Veza assesses risk for each identity independently and records each risk on the identity that a risk query matches. Correlating a person's identities does not combine or transfer their risk scores, so covering every identity provider comes down to making sure a risk query evaluates each provider's users.

Built-in Veza risk queries are rooted at specific provider user types, such as Okta and Active Directory users. A query rooted at one provider's user type evaluates only that provider, so a provider that has no risk queries of its own, such as Azure AD, can be left without risk coverage.

To assess risk uniformly across every identity provider, author your risk queries against a user supertype instead of a single provider's user type. Every provider's user type derives from a shared user supertype, so one supertype query evaluates users from every identity provider and records risk on each. This reaches providers that have no built-in queries of their own, without maintaining a separate query for each provider. See [Query Builder](/4yItIzMvkpAvMVFAamTf/features/search/query-builder.md) for selecting an entity type or supertype as the query source, and [Risks](/4yItIzMvkpAvMVFAamTf/features/insights/risks.md) for assigning risk levels.

{% hint style="info" %}
Veza assesses and records risk separately for each identity. Correlating a person's identities with identity mappings lets you see their access across providers together, but it does not combine their risk scores. To cover every provider, author your risk queries against a user supertype.
{% endhint %}

### When you need a custom mapping

Configure a mapping when any of these apply:

* The two systems have no automatic correlation between them. See [Automatic Identity Matching](/4yItIzMvkpAvMVFAamTf/integrations/configuration/automatic-identity-matching.md) for what Veza covers.
* The only value the two systems share is an attribute Veza does not compare automatically, such as an employee ID, a secondary email address, an email alias, or a custom property.
* The values are equivalent but not identical, and need a domain removed, punctuation ignored, or a naming convention applied.
* You are connecting a custom application or custom identity provider built with the [Open Authorization API](/4yItIzMvkpAvMVFAamTf/developers/api/oaa.md) whose identity values do not match an attribute Veza compares.

{% hint style="warning" %}
For **Active Directory to Entra ID** and **Okta to Google Workspace**, configuring a mapping replaces the automatic correlation between those two providers. Remove the mapping to restore the automatic behavior.

For every other combination, a mapping is additive: it creates its own relationships alongside anything Veza matched automatically.
{% endhint %}

### Prerequisites

Before configuring identity mappings:

* Integrate both the source and destination systems with Veza, and confirm each has completed an extraction
* Verify you have permission to modify integration configurations
* Identify the attribute or pattern that correlates identities across the two systems

An OAA application appears in the destination list only after it has pushed data at least once, because Veza builds that list from the entity types present in Access Graph.

### Enabling Identity Correlation

To enable custom mappings for an identity or cloud provider:

1. Go to the **Integrations** page.
2. Select a cloud or identity provider from the list and select **Edit**.
3. Open the **Mapping Configuration** step.
4. Select **Add Mapping Configuration**.
   1. Enable **Use email by default** to compare email addresses when no property matcher is configured. Any property matcher you add takes precedence, and Veza ignores this setting.
   2. For **Mapping Mode**, choose:
      * **Users** to correlate individual identities across systems
      * **Groups** to connect source and destination groups
      * **Roles to Users** (AWS only) to map AWS IAM roles to application local users
   3. For **Destination Data Source Type**, select the target system. Applications built with OAA appear as the application type followed by the data source type, such as `MyApp (Custom Application)`.
   4. Select **Add Property Matcher** and choose the source and destination properties, described in [Property matchers](#property-matchers).
   5. Optionally select **Transformations**, described in [Transformations](#transformations).
5. Add more property matchers as needed. With more than one matcher, an **OR** and **AND** toggle appears, described in [Combining matchers with OR and AND](#combining-matchers-with-or-and-and).
6. Select **Save Configuration**.

Each mapping configuration covers one destination data source type per mapping mode. To correlate both identities and groups with the same destination, add two mappings, one in each mode. A mapping cannot target the source provider itself, such as one Okta domain to another, and Veza rejects a set of mappings that would form a loop between providers.

{% hint style="warning" %}
If you configure any property matchers, Veza ignores the **Use email by default** setting. For example, with **Use email by default** enabled and a property matcher for `username` to `user_id`, Veza uses only the username matcher.
{% endhint %}

#### Property matchers

A property matcher names the property to compare on each side. Both dropdowns offer the same five options:

* **Unique ID**: the identity's unique identifier. Veza reads the `identity_unique_id`, `identity_unique_ids`, and `idp_unique_id` properties.
* **Email**: the identity's email address. Veza reads the `email` and `emails` properties.
* **Property**: any other property on the entity, entered by name, such as `employee_id`, `user_principal_name`, or `account_name`. Use this to correlate on an attribute that automatic matching does not compare. Property names are not case-sensitive, and `id` and `name` are valid values.
* **Custom Property**: a [custom property](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/best-practices/oaa-custom-properties.md) on an OAA entity, entered without the `customprop_` prefix, such as `employee_id`.
* **Template**: an expression that transforms property values before comparing them, for matching different naming conventions. See [Identity Mapping Templates](/4yItIzMvkpAvMVFAamTf/integrations/configuration/identity-mapping-templates.md).

The two sides do not have to use the same option. Mapping the Okta **Property** `employee_id` to a custom application's **Custom Property** `employee_id` is the supported way to correlate on employee ID, which Veza does not compare automatically.

{% hint style="info" %}
For **Property** and **Custom Property**, Veza compares the first value when a property holds a list. For **Unique ID**, **Email**, and **Template**, Veza compares every value in the list.
{% endhint %}

#### Transformations

Transformations adjust values on both sides before Veza compares them:

* **Ignore Special**: removes characters that are not letters or digits from the name portion of the value. A domain, if present, stays intact.
* **Ignore Domain**: removes the domain portion of the value. Veza recognizes both `user@domain` and `DOMAIN\user` forms.

Enable both to compare `DOMAIN\j.smith` with `jsmith`.

#### Combining matchers with OR and AND

When more than one property matcher is defined, an **OR** and **AND** toggle appears in the upper-right corner of the property matchers section:

* **OR**, the default: a match on **any** property matcher correlates the identities. Use OR when identities may follow different conventions across systems.
* **AND**: **all** property matchers must match. Use AND for stricter correlation when you need high-confidence matches based on multiple attributes.

An OR configuration such as this matches any of `john.smith`, `jsmith`, or `john.smith@company.com` for a user named John Smith:

```txt
Template: {FirstName}.{LastName} OR
Template: {FirstInitial}{LastName} OR
Property: email
```

An AND configuration such as this correlates a user only when both attributes align, which reduces false positives where names or email domains are shared:

```txt
Property: email AND
Property: department
```

### Template transformations

A **Template** property matcher compares transformed values instead of raw ones, which correlates identities that follow different naming conventions in each system. A template expression can reference any property on the entity and chain functions such as `LOWER`, `REMOVE_DOMAIN`, and `SUB_STRING`.

#### Transformation functions

For the template syntax, the properties Veza provides, and every supported transformation function, see [Identity Mapping Templates](/4yItIzMvkpAvMVFAamTf/integrations/configuration/identity-mapping-templates.md).

### Identity matchers

Identity matchers correlate two specific identities by name, for the accounts your property matchers cannot cover:

1. Select **Add Identity Matcher**.
2. In the leftmost dropdown, choose an identity from the source integration.
3. In the rightmost dropdown, choose the corresponding identity in the destination data source.

Veza evaluates identity matchers only for destination identities that no property matcher resolved, so they act as exceptions rather than overrides. Identity matchers are available when editing an existing integration, after both sides have extracted, and are not available for OAA-based sources.

### When a mapping takes effect

Saving a mapping does not create relationships on its own. Veza applies the configuration during the next extraction and parse of the **source** integration, and the relationships appear when that completes. To apply a mapping sooner, run an extraction on the source integration.

Query paths become available as soon as you save, so a query can reference the relationship before any relationships exist.

### How Veza compares values

* Comparison ignores case on both sides. `Jane.Doe@company.com` and `jane.doe@company.com` are equivalent.
* Empty values do not match, including when a transformation reduces a value to an empty string.
* Every match creates a relationship. If a destination identity matches several source identities, Veza creates a relationship for each, so keep the compared values unique when you need a single correlation.
* Relationships created by a mapping are distinct from those created by automatic matching, which is why both can exist between the same two systems.

### Examples

Configure mappings for one or more target data sources based on entity attributes, or use templates to correlate identities and groups across multiple destination data sources.

#### User identity mapping

1. Active Directory to SQL Server:
   * Source: Active Directory user email `admin@yourdomain.com`
   * Destination: SQL login `YOURDOMAIN\admin`
   * Configuration: map **Email** to **Unique ID**, with **Ignore Domain** enabled
2. Okta to a custom application:
   * Source: Okta user email `jane.doe@company.com`
   * Destination: application username `jdoe`
   * Configuration: map **Email** to **Custom Property** `username`
3. Okta to a custom application, correlating on employee ID:
   * Source: Okta **Property** `employee_id`
   * Destination: application **Custom Property** `employee_id`
   * Configuration: use this when the two systems share only an employee ID, which automatic matching does not compare
4. Entra ID to PingOne:
   * Source: Entra ID **Property** `user_principal_name`, holding `admin@company.com`
   * Destination: PingOne user **Email** `admin@company.com`
   * Configuration: correlates principal name to email for cross-service access reviews

#### Group identity mapping

1. Entra ID to GitHub:
   * Source: Entra ID group `Engineering-Team`
   * Destination: GitHub team `Engineering Team`
   * Configuration: map name to name, with **Ignore Special** enabled
2. Okta to Snowflake:
   * Source: Okta group `DataAnalysts`
   * Destination: Snowflake role `DATA_ANALYSTS`
   * Configuration: map name to name, using a template with the `UPPER` function
3. Okta to a custom application:
   * Source: Okta group `Engineering-Team`
   * Destination: custom application group `Engineering-Team`
   * Configuration: map name to name for group-based access visibility in OAA applications
4. Multiple destinations:
   * Source: Active Directory security group `Finance-Staff`
   * Destinations: Salesforce group `Finance Users`, AWS IAM group `finance-users`, and Box group `Finance Department`
   * Configuration: a single mapping configuration applying to multiple destination systems

#### Role to user identity mapping (AWS only)

AWS integrations support mapping IAM roles directly to local users in downstream applications. This is useful when IAM roles represent service accounts or federated identities that correspond to application-level users.

1. AWS IAM role to custom application user:
   * Source: AWS IAM role `DataAnalyticsRole`
   * Destination: custom application user `analytics-service`
   * Configuration: map role name to custom property `service_account`
2. AWS IAM role to Snowflake user:
   * Source: AWS IAM role `DataEngineerRole`
   * Destination: Snowflake user `data_engineer`
   * Configuration: map role name to unique ID

To configure role to user mapping:

1. Edit your AWS integration and open **Mapping Configuration**.
2. Select **Roles to Users** as the mapping mode.
3. Choose a destination data source type, such as Custom Application, Snowflake, or SQL Server.
4. Add property matchers to define how role attributes map to user attributes.

{% hint style="info" %}
The **Roles to Users** mapping mode is available for AWS integrations only.
{% endhint %}

### Supported sources and destinations

Configure a mapping on the source integration. These integrations can hold a mapping configuration:

* Active Directory, Entra ID (Azure AD), Google Workspace, Okta, OneLogin, and PingOne
* AWS, which also supports the **Roles to Users** mapping mode
* Workday
* Sources built with OAA: custom identity providers, secret stores, and HRIS sources, including CSV HRIS uploads, Database HRIS, LDAP, and HRIS connectors such as HiBob, Personio, and Oracle HCM

{% hint style="info" %}
A CSV-uploaded application cannot hold a mapping configuration. Configure the mapping on the identity provider instead, and select the application as the destination. CSV HRIS uploads do hold their own mapping configuration.
{% endhint %}

Available destinations:

* **Identity providers**: Active Directory, Entra ID (Azure AD), Google Workspace, Okta, OneLogin, PingOne, AWS Identity Center, Oracle Cloud IAM domains, CyberArk Identity
* **Databases and warehouses**: Snowflake, Trino, SQL Server and Azure SQL (server logins and per-database users), Oracle Database, AWS Redshift, AWS RDS for MySQL, AWS RDS for PostgreSQL
* **Cloud and platform**: AWS IAM, Databricks workspaces and AWS Databricks accounts, HashiCorp Vault namespaces, Privacera
* **Applications**: GitHub users and organizations, Salesforce, Salesforce Commerce Cloud, Box, ServiceNow, Workday, SAP ECC, Oracle E-Business Suite, Veza
* **Built with OAA**: custom applications, custom principals, and custom identity providers

{% hint style="info" %}
For SQL Server and Azure SQL, the destination list includes the server entry for logins and the database entry for per-database users. Choose the **SQL Server Database** or **Azure SQL Database** entry when the mapping needs to reach Windows-authenticated database users that have no corresponding server login.
{% endhint %}

To map identities to many destinations from one configuration, contact your Veza support representative to enable that capability. When enabled, **Destination Data Source Types** accepts more than one selection.

{% hint style="info" %}
A mapping whose destination is the generic `CUSTOM_APPLICATION` type is read-only. You can keep or remove it, but not edit it. Create new mappings against a specific application type instead.
{% endhint %}

### Related

* [Automatic Identity Matching](/4yItIzMvkpAvMVFAamTf/integrations/configuration/automatic-identity-matching.md) for the attributes Veza compares without configuration
* [Identity Mapping Templates](/4yItIzMvkpAvMVFAamTf/integrations/configuration/identity-mapping-templates.md) for template expressions and transformation functions
* [Cross-service connections](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/best-practices/cross-service-connections.md) for setting identity values in an OAA payload


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/integrations/configuration/custom-identity-mappings.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
