Configure synchronization with directory extension attributes
Article
Namespace: microsoft.graph
You can customize your synchronization schema to include Azure Active Directory (Azure AD) directory extension attributes. This article describes how to use a directory extension attribute (extension_9d98asdfl15980a_Nickname) to populate the value of User.CommunityNickname in Salesforce. In this scenario, you have Azure AD Connect set up to provision a number of directory extension attributes from Windows Server Active Directory on-premises to 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 Sandbox".
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)
The {jobId} is SfSandboxOutDelta.e4bbf44533ea4eabb17027f3a92e92aa.
Find the name of the directory extension attribute you need
You'll need the full name of the extension attribute. If you don't know the full name (which should look similar to extension_9d98asdfl15980a_Nickname), see the following information about directory extension attributes and how to inspect them:
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)
Add an attribute definition for the extension_9d98asdfl15980a_Nickname attribute.
Under directories, find the directory with the name "Azure Active Directory", 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 extension_9d98asdfl15980a_Nickname and CommunityNickname.
Under synchronizationRules, find the rule that specifies Azure AD as 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.