Configure synchronization with custom target attributes
Article
Namespace: microsoft.graph
You can customize your synchronization schema to include custom attributes that are defined in the target directory. This article describes how to customize a Salesforce subscription by adding a new field called officeCode. You set up synchronization from Azure Active Directory (Azure AD) to Salesforce, and for each user, you will populate the officeCode field in Salesforce with the value from the extensionAttribute10 field in Azure AD.
This article assumes that you have already added an application that supports synchronization to your tenant through the Microsoft Entra admin center, that you know the application display name, and that you have an authorization token for Microsoft Graph. For information about how to get the authorization token, see Get access tokens to call Microsoft Graph.
Find the service principal object by display name
The following example shows how to find a service principal object with the display name Salesforce.
GET https://graph.microsoft.com/v1.0/servicePrincipals?$select=id,appId,displayName&$filter=startswith(displayName, 'salesforce')
Authorization: Bearer {Token}
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var result = await graphClient.ServicePrincipals.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Select = new string []{ "id","appId","displayName" };
requestConfiguration.QueryParameters.Filter = "startswith(displayName, 'salesforce')";
requestConfiguration.Headers.Add("Authorization", "Bearer {Token}");
});
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals list --filter "startswith(displayName, 'salesforce')" --select "id,appId,displayName"
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestConfiguration = new ServicePrincipalsRequestBuilderGetRequestConfiguration();
$headers = [
'Authorization' => 'Bearer {Token}',
];
$requestConfiguration->headers = $headers;
$queryParameters = ServicePrincipalsRequestBuilderGetRequestConfiguration::createQueryParameters();
$queryParameters->select = ["id","appId","displayName"];
$queryParameters->filter = "startswith(displayName, 'salesforce')";
$requestConfiguration->queryParameters = $queryParameters;
$result = $graphServiceClient->servicePrincipals()->get($requestConfiguration)->wait();
GET https://graph.microsoft.com/v1.0/servicePrincipals/60443998-8cf7-4e61-b05c-a53b658cb5e1/synchronization/jobs
Authorization: Bearer {Token}
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].Synchronization.Jobs.GetAsync((requestConfiguration) =>
{
requestConfiguration.Headers.Add("Authorization", "Bearer {Token}");
});
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestConfiguration = new JobsRequestBuilderGetRequestConfiguration();
$headers = [
'Authorization' => 'Bearer {Token}',
];
$requestConfiguration->headers = $headers;
$result = $graphServiceClient->servicePrincipals()->byServicePrincipalId('servicePrincipal-id')->synchronization()->jobs()->get($requestConfiguration)->wait();
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_configuration = JobsRequestBuilder.JobsRequestBuilderGetRequestConfiguration(
headers = {
'Authorization' : "Bearer {Token}",
}
)
result = await graph_client.service_principals.by_service_principal_id('servicePrincipal-id').synchronization.jobs.get(request_configuration = request_configuration)
GET https://graph.microsoft.com/v1.0/servicePrincipals/{servicePrincipalId}/synchronization/jobs/{jobId}/schema
Authorization: Bearer {Token}
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].Synchronization.Jobs["{synchronizationJob-id}"].Schema.GetAsync((requestConfiguration) =>
{
requestConfiguration.Headers.Add("Authorization", "Bearer {Token}");
});
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc service-principals synchronization jobs schema get --service-principal-id {servicePrincipal-id} --synchronization-job-id {synchronizationJob-id}
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestConfiguration = new SchemaRequestBuilderGetRequestConfiguration();
$headers = [
'Authorization' => 'Bearer {Token}',
];
$requestConfiguration->headers = $headers;
$result = $graphServiceClient->servicePrincipals()->byServicePrincipalId('servicePrincipal-id')->synchronization()->jobs()->bySynchronizationJobId('synchronizationJob-id')->schema()->get($requestConfiguration)->wait();
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_configuration = SchemaRequestBuilder.SchemaRequestBuilderGetRequestConfiguration(
headers = {
'Authorization' : "Bearer {Token}",
}
)
result = await graph_client.service_principals.by_service_principal_id('servicePrincipal-id').synchronization.jobs.by_job_id('synchronizationJob-id').schema.get(request_configuration = request_configuration)
Under directories, find the directory with the name salesforce.com, and in the object's array, find the one named User.
Add the new attribute to the list, specifying the name and type, as shown in the following example.
Add an attribute mapping between officeCode and extensionAttribute10.
Under synchronizationRules, find the rule that specifies Azure AD as the source directory, and Salesforce.com as the target directory ("sourceDirectoryName": "Azure Active Directory", "targetDirectoryName": "salesforce.com").
In the objectMappings of the rule, find the mapping between users ("sourceObjectName": "User", "targetObjectName": "User").
In the attributeMappings array of the objectMapping, add a new entry, as shown in the following example.
When you save the updated synchronization schema, make sure that you include the entire schema, including the unmodified parts. This request will replace the existing schema with the one that you provide.
If the schema was saved successfully, the request returns a 204 No Content response code. On the next iteration of the synchronization job, it will start re-processing all the accounts in your Azure AD, and the new mappings will be applied to all provisioned accounts.