Namespace: microsoft.graph
You can customize your synchronization schema to include Microsoft Entra 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 Microsoft Entra Connect set up to provision a number of directory extension attributes from Windows Server Active Directory on-premises to Microsoft Entra ID.
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".
Request
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
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
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}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphserviceprincipals "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"
//other-imports
)
headers := abstractions.NewRequestHeaders()
headers.Add("Authorization", "Bearer {Token}")
requestFilter := "startswith(displayName, 'salesforce')"
requestParameters := &graphserviceprincipals.ServicePrincipalsRequestBuilderGetQueryParameters{
Select: [] string {"id","appId","displayName"},
Filter: &requestFilter,
}
configuration := &graphserviceprincipals.ServicePrincipalsRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: requestParameters,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
servicePrincipals, err := graphClient.ServicePrincipals().Get(context.Background(), configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ServicePrincipalCollectionResponse result = graphClient.servicePrincipals().get(requestConfiguration -> {
requestConfiguration.queryParameters.select = new String []{"id", "appId", "displayName"};
requestConfiguration.queryParameters.filter = "startswith(displayName, 'salesforce')";
requestConfiguration.headers.add("Authorization", "Bearer {Token}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
const options = {
authProvider,
};
const client = Client.init(options);
let servicePrincipals = await client.api('/servicePrincipals')
.header('Authorization','Bearer {Token}')
.filter('startswith(displayName, \'salesforce\')')
.select('id,appId,displayName')
.get();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\ServicePrincipals\ServicePrincipalsRequestBuilderGetRequestConfiguration;
$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();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
Import-Module Microsoft.Graph.Applications
Get-MgServicePrincipal -Property "id,appId,displayName" -Filter "startswith(displayName, 'salesforce')"
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.service_principals.service_principals_request_builder import ServicePrincipalsRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
query_params = ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetQueryParameters(
select = ["id","appId","displayName"],
filter = "startswith(displayName, 'salesforce')",
)
request_configuration = RequestConfiguration(
query_parameters = query_params,
)
request_configuration.headers.add("Authorization", "Bearer {Token}")
result = await graph_client.service_principals.get(request_configuration = request_configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals(id,appId,displayName)",
"value": [
{
"id": "167e33e9-f80e-490e-b4d8-698d4a80fb3e",
"appId": "cd3ed3de-93ee-400b-8b19-b61ef44a0f29",
"displayName": "Salesforce"
},
{
"id": "8cbbb70b-7290-42da-83ee-89fa3517a977",
"appId": "b0f2e3b1-fe31-4658-b216-44dcaeabb63a",
"displayName": "salesforce 1"
},
{
"id": "60443998-8cf7-4e61-b05c-a53b658cb5e1",
"appId": "79079396-c301-405d-900f-e2e0c2439a90",
"displayName": "Salesforce Sandbox"
}
]
}
The {servicePrincipalId}
is 60443998-8cf7-4e61-b05c-a53b658cb5e1
.
List synchronization jobs in the context of the service principal
The following example shows you how to get the jobId
that you need to work with. Generally, the response returns only one job.
Request
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
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].Synchronization.Jobs.GetAsync((requestConfiguration) =>
{
requestConfiguration.Headers.Add("Authorization", "Bearer {Token}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphserviceprincipals "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"
//other-imports
)
headers := abstractions.NewRequestHeaders()
headers.Add("Authorization", "Bearer {Token}")
configuration := &graphserviceprincipals.ItemSynchronizationJobsRequestBuilderGetRequestConfiguration{
Headers: headers,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
jobs, err := graphClient.ServicePrincipals().ByServicePrincipalId("servicePrincipal-id").Synchronization().Jobs().Get(context.Background(), configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
SynchronizationJobCollectionResponse result = graphClient.servicePrincipals().byServicePrincipalId("{servicePrincipal-id}").synchronization().jobs().get(requestConfiguration -> {
requestConfiguration.headers.add("Authorization", "Bearer {Token}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
const options = {
authProvider,
};
const client = Client.init(options);
let jobs = await client.api('/servicePrincipals/60443998-8cf7-4e61-b05c-a53b658cb5e1/synchronization/jobs')
.header('Authorization','Bearer {Token}')
.get();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\ServicePrincipals\Item\Synchronization\Jobs\JobsRequestBuilderGetRequestConfiguration;
$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();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.service_principals.item.synchronization.jobs.jobs_request_builder import JobsRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
request_configuration = RequestConfiguration()
request_configuration.headers.add("Authorization", "Bearer {Token}")
result = await graph_client.service_principals.by_service_principal_id('servicePrincipal-id').synchronization.jobs.get(request_configuration = request_configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals('60443998-8cf7-4e61-b05c-a53b658cb5e1')/synchronization/jobs",
"value": [
{
"id": "SfSandboxOutDelta.e4bbf44533ea4eabb17027f3a92e92aa",
"templateId": "SfSandboxOutDelta",
"schedule": {},
"status": {}
}
]
}
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 the synchronization schema
The following example shows how to get the synchronization schema.
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
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals["{servicePrincipal-id}"].Synchronization.Jobs["{synchronizationJob-id}"].Schema.GetAsync((requestConfiguration) =>
{
requestConfiguration.Headers.Add("Authorization", "Bearer {Token}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
mgc service-principals synchronization jobs schema get --service-principal-id {servicePrincipal-id} --synchronization-job-id {synchronizationJob-id}
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphserviceprincipals "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"
//other-imports
)
headers := abstractions.NewRequestHeaders()
headers.Add("Authorization", "Bearer {Token}")
configuration := &graphserviceprincipals.ItemSynchronizationJobsItemSchemaRequestBuilderGetRequestConfiguration{
Headers: headers,
}
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
schema, err := graphClient.ServicePrincipals().ByServicePrincipalId("servicePrincipal-id").Synchronization().Jobs().BySynchronizationJobId("synchronizationJob-id").Schema().Get(context.Background(), configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
SynchronizationSchema result = graphClient.servicePrincipals().byServicePrincipalId("{servicePrincipal-id}").synchronization().jobs().bySynchronizationJobId("{synchronizationJob-id}").schema().get(requestConfiguration -> {
requestConfiguration.headers.add("Authorization", "Bearer {Token}");
});
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
const options = {
authProvider,
};
const client = Client.init(options);
let synchronizationSchema = await client.api('/servicePrincipals/{servicePrincipalId}/synchronization/jobs/{jobId}/schema')
.header('Authorization','Bearer {Token}')
.get();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\ServicePrincipals\Item\Synchronization\Jobs\Item\Schema\SchemaRequestBuilderGetRequestConfiguration;
$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();
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
Import-Module Microsoft.Graph.Applications
Get-MgServicePrincipalSynchronizationJobSchema -ServicePrincipalId $servicePrincipalId -SynchronizationJobId $synchronizationJobId
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.service_principals.item.synchronization.jobs.item.schema.schema_request_builder import SchemaRequestBuilder
from kiota_abstractions.base_request_configuration import RequestConfiguration
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
request_configuration = RequestConfiguration()
request_configuration.headers.add("Authorization", "Bearer {Token}")
result = await graph_client.service_principals.by_service_principal_id('servicePrincipal-id').synchronization.jobs.by_synchronization_job_id('synchronizationJob-id').schema.get(request_configuration = request_configuration)
Read the SDK documentation for details on how to add the SDK to your project and create an authProvider instance.
Note: The response object shown here might be shortened for readability. All the properties will be returned in an actual call.
HTTP/1.1 200 OK
Content-Type: application/json
{
"directories": [
{
"id": "66e4a8cc-1b7b-435e-95f8-f06cea133828",
"name": "Azure Active Directory",
"objects": [
{
"attributes": [
{
"anchor": true,
"caseExact": false,
"defaultValue": null,
"metadata": [],
"multivalued": false,
"mutability": "ReadWrite",
"name": "objectId",
"required": false,
"referencedObjects": [],
"type": "String"
},
{
"anchor": false,
"caseExact": false,
"defaultValue": null,
"metadata": [],
"multivalued": false,
"mutability": "ReadWrite",
"name": "streetAddress",
"required": false,
"referencedObjects": [],
"type": "String"
}
],
"name": "User"
}
]
},
{
"id": "8ffa6169-f354-4751-9b77-9c00765be92d",
"name": "salesforce.com",
"objects": []
}
],
"synchronizationRules": [
{
"editable": true,
"id": "4c5ecfa1-a072-4460-b1c3-4adde3479854",
"name": "USER_OUTBOUND_USER",
"objectMappings": [
{
"attributeMappings": [
{
"defaultValue": "True",
"exportMissingReferences": false,
"flowBehavior": "FlowWhenChanged",
"flowType": "Always",
"matchingPriority": 0,
"source": {
"expression": "Not([IsSoftDeleted])",
"name": "Not",
"parameters": [
{
"key": "source",
"value": {
"expression": "[IsSoftDeleted]",
"name": "IsSoftDeleted",
"parameters": [],
"type": "Attribute"
}
}
],
"type": "Function"
},
"targetAttributeName": "IsActive"
}
],
"enabled": true,
"flowTypes": "Add, Update, Delete",
"name": "Synchronize Azure Active Directory Users to salesforce.com",
"scope": null,
"sourceObjectName": "User",
"targetObjectName": "User"
}
]
}
]
}
Add a definition for the directory extension attribute, and a mapping between the attributes
Use a plain text editor of your choice (for example, Notepad++ or JSON Editor Online) to:
Add an attribute definition for the extension_9d98asdfl15980a_Nickname
attribute.
- Under directories, find the directory with the name "Microsoft Entra ID", 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 Microsoft Entra ID 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.
{
"directories": [
{
"id": "66e4a8cc-1b7b-435e-95f8-f06cea133828",
"name": "Azure Active Directory",
"objects": [
{
"attributes": [
,{
"name": "extension_9d98asdfl15980a_Nickname",
"type": "String"
}
],
"name":"User"
}]
}
],
"synchronizationRules": [
{
"editable": true,
"id": "4c5ecfa1-a072-4460-b1c3-4adde3479854",
"metadata": [..],
"name": "USER_OUTBOUND_USER",
"objectMappings": [
{
"attributeMappings": [
,{
"source": {
"name": "extension_9d98asdfl15980a_Nickname",
"type": "Attribute"
},
"targetAttributeName": "CommunityNickname"
}
],
"name": "Synchronize Azure Active Directory Users to salesforce.com",
"scope": null,
"sourceObjectName": "User",
"targetObjectName": "User"
}
],
"priority": 1,
"sourceDirectoryName": "Azure Active Directory",
"targetDirectoryName": "salesforce.com"
},
]
}
Save the modified synchronization schema
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.
PUT https://graph.microsoft.com/v1.0/servicePrincipals/{servicePrincipalId}/synchronization/jobs/{jobId}/schema
Authorization: Bearer {Token}
{
"directories": [],
"synchronizationRules": []
}
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 Microsoft Entra ID, and the new mappings will be applied to all provisioned accounts.
Related content