Configure a custom claim provider token issuance event (preview)
Article
This article describes how to configure and set up a custom claims provider with the token issuance start event type. This event is triggered right before the token is issued, and allows you to call a REST API to add claims to the token.
This how-to guide demonstrates the token issuance start event with a REST API running in Azure Functions and a sample OpenID Connect application. Before you start, take a look at following video, which demonstrates how to configure Microsoft Entra custom claims provider with Function App:
To use Azure services, including Azure Functions, you need an Azure subscription. If you don't have an existing Azure account, you may sign up for a free trial or use your Visual Studio Subscription benefits when you create an account.
Step 1: Create an Azure Function app
Tip
Steps in this article may vary slightly based on the portal you start from.
In this step, you create an HTTP trigger function API in the Azure portal. The function API is the source of extra claims for your token. Follow these steps to create an Azure Function:
Sign in to the Azure portal with your administrator account.
From the Azure portal menu or the Home page, select Create a resource.
In the New page, select Compute > Function App.
On the Basics page, use the function app settings as specified in the following table:
Setting
Suggested value
Description
Subscription
Your subscription
The subscription under which the new function app will be created in.
Select and existing resource group, or name for the new one in which you'll create your function app.
Function App name
Globally unique name
A name that identifies the new function app. Valid characters are a-z (case insensitive), 0-9, and -.
Publish
Code
Option to publish code files or a Docker container. For this tutorial, select Code.
Runtime stack
.NET
Your preferred programming language. For this tutorial, select .NET.
Version
6
Version of the .NET runtime.
Region
Preferred region
Select a region that's near you or near other services that your functions can access.
Operating System
Windows
The operating system is pre-selected for you based on your runtime stack selection.
Plan type
Consumption (Serverless)
Hosting plan that defines how resources are allocated to your function app.
Select Review + create to review the app configuration selections and then select Create.
Select the Notifications icon in the upper-right corner of the portal and watch for the Deployment succeeded message. Then, select Go to resource to view your new function app.
1.1 Create an HTTP trigger function
After the Azure Function app is created, create an HTTP trigger function. The HTTP trigger lets you invoke a function with an HTTP request. This HTTP trigger will be referenced and called by your Microsoft Entra custom authentication extension.
Within your Function App, from the menu select Functions.
From the top menu, select + Create.
In the Create Function window, leave the Development environment property as Develop in portal, and then select the HTTP trigger template.
Under Template details, enter CustomAuthenticationExtensionsAPI for the New Function property.
For the Authorization level, select Function.
Select Create
The following screenshot demonstrates how to configure the Azure HTTP trigger function.
1.2 Edit the function
From the menu, select Code + Test
Replace the entire code with the following code snippet.
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
// Read the correlation ID from the Azure AD request
string correlationId = data?.data.authenticationContext.correlationId;
// Claims to return to Azure AD
ResponseContent r = new ResponseContent();
r.data.actions[0].claims.CorrelationId = correlationId;
r.data.actions[0].claims.ApiVersion = "1.0.0";
r.data.actions[0].claims.DateOfBirth = "01/01/2000";
r.data.actions[0].claims.CustomRoles.Add("Writer");
r.data.actions[0].claims.CustomRoles.Add("Editor");
return new OkObjectResult(r);
}
public class ResponseContent{
[JsonProperty("data")]
public Data data { get; set; }
public ResponseContent()
{
data = new Data();
}
}
public class Data{
[JsonProperty("@odata.type")]
public string odatatype { get; set; }
public List<Action> actions { get; set; }
public Data()
{
odatatype = "microsoft.graph.onTokenIssuanceStartResponseData";
actions = new List<Action>();
actions.Add(new Action());
}
}
public class Action{
[JsonProperty("@odata.type")]
public string odatatype { get; set; }
public Claims claims { get; set; }
public Action()
{
odatatype = "microsoft.graph.tokenIssuanceStart.provideClaimsForToken";
claims = new Claims();
}
}
public class Claims{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string CorrelationId { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string DateOfBirth { get; set; }
public string ApiVersion { get; set; }
public List<string> CustomRoles { get; set; }
public Claims()
{
CustomRoles = new List<string>();
}
}
The code starts with reading the incoming JSON object. Microsoft Entra ID sends the JSON object to your API. In this example, it reads the correlation ID value. Then, the code returns a collection of claims, including the original correlation ID, the version of your Azure Function, date of birth and custom role that is returned to Microsoft Entra ID.
From the top menu, select Get Function Url, and copy the URL. In the next step, the function URL will be used and referred to as {Function_Url}.
Step 2: Register a custom authentication extension
In this step, you configure a custom authentication extension, which will be used by Microsoft Entra ID to call your Azure function. The custom authentication extension contains information about your REST API endpoint, the claims that it parses from your REST API, and how to authenticate to your REST API. Follow these steps to register a custom authentication extension:
Browse to Identity > Applications > Enterprise applications.
Select Custom authentication extensions, and then select Create a custom authentication extension.
In Basics, select the tokenIssuanceStart event and select Next.
In Endpoint Configuration, fill in the following properties:
Name - A name for your custom authentication extension. For example, Token issuance event.
Target Url - The {Function_Url} of your Azure Function URL.
Description - A description for your custom authentication extensions.
Select Next.
In API Authentication, select the Create new app registration option to create an app registration that represents your function app.
Give the app a name, for example Azure Functions authentication events API.
Select Next.
In Claims, enter the attributes that you expect your custom authentication extension to parse from your REST API and will be merged into the token. Add the following claims:
dateOfBirth
customRoles
apiVersion
correlationId
Select Next and Create, which registers the custom authentication extension and the associated application registration.
Register an application to authenticate your custom authentication extension to your Azure Function.
Sign in to Graph Explorer using an account whose home tenant is the tenant you wish to manage your custom authentication extension in. The account must have the privileges to create and manage an application registration in the tenant.
POST https://graph.microsoft.com/v1.0/applications
Content-type: application/json
{
"displayName": "authenticationeventsAPI"
}
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new Application
{
DisplayName = "My application",
};
var result = await graphClient.Applications.PostAsync(requestBody);
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_body = Application(
display_name = "My application",
)
result = await graph_client.applications.post(body = request_body)
From the response, record the value of id and appId of the newly created app registration. These values will be referenced in this article as {authenticationeventsAPI_ObjectId} and {authenticationeventsAPI_AppId} respectively.
Create a service principal in the tenant for the authenticationeventsAPI app registration.
Still in Graph Explorer, run the following request. Replace {authenticationeventsAPI_AppId} with the value of appId that you recorded from the previous step.
POST https://graph.microsoft.com/v1.0/servicePrincipals
Content-type: application/json
{
"appId": "{authenticationeventsAPI_AppId}"
}
Set the App ID URI, access token version, and required resource access
Update the newly created application to set the application ID URI value, the access token version, and the required resource access.
In Graph Explorer, run the following request.
Set the application ID URI value in the identifierUris property. Replace {Function_Url_Hostname} with the hostname of the {Function_Url} you recorded earlier.
Set the {authenticationeventsAPI_AppId} value with the appId that you recorded earlier.
An example value is api://authenticationeventsAPI.azurewebsites.net/f4a70782-3191-45b4-b7e5-dd415885dd80. Take note of this value as you'll use it later in this article in place of {functionApp_IdentifierUri}.
Next, you register the custom authentication extension. You register the custom authentication extension by associating it with the app registration for the Azure Function, and your Azure Function endpoint {Function_Url}.
In Graph Explorer, run the following request. Replace {Function_Url} with the hostname of your Azure Function app. Replace {functionApp_IdentifierUri} with the identifierUri used in the previous step.
You'll need the CustomAuthenticationExtension.ReadWrite.All delegated permission.
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new OnTokenIssuanceStartCustomExtension
{
OdataType = "#microsoft.graph.onTokenIssuanceStartCustomExtension",
DisplayName = "onTokenIssuanceStartCustomExtension",
Description = "Fetch additional claims from custom user store",
EndpointConfiguration = new HttpRequestEndpoint
{
OdataType = "#microsoft.graph.httpRequestEndpoint",
TargetUrl = "https://authenticationeventsAPI.contoso.com",
},
AuthenticationConfiguration = new AzureAdTokenAuthentication
{
OdataType = "#microsoft.graph.azureAdTokenAuthentication",
ResourceId = "api://authenticationeventsAPI.contoso.com/a13d0fc1-04ab-4ede-b215-63de0174cbb4",
},
ClientConfiguration = new CustomExtensionClientConfiguration
{
TimeoutInMilliseconds = 2000,
MaximumRetries = 1,
},
ClaimsForTokenConfiguration = new List<OnTokenIssuanceStartReturnClaim>
{
new OnTokenIssuanceStartReturnClaim
{
ClaimIdInApiResponse = "DateOfBirth",
},
new OnTokenIssuanceStartReturnClaim
{
ClaimIdInApiResponse = "CustomRoles",
},
},
};
var result = await graphClient.Identity.CustomAuthenticationExtensions.PostAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new OnTokenIssuanceStartCustomExtension();
$requestBody->setOdataType('#microsoft.graph.onTokenIssuanceStartCustomExtension');
$requestBody->setDisplayName('onTokenIssuanceStartCustomExtension');
$requestBody->setDescription('Fetch additional claims from custom user store');
$endpointConfiguration = new HttpRequestEndpoint();
$endpointConfiguration->setOdataType('#microsoft.graph.httpRequestEndpoint');
$endpointConfiguration->setTargetUrl('https://authenticationeventsAPI.contoso.com');
$requestBody->setEndpointConfiguration($endpointConfiguration);
$authenticationConfiguration = new AzureAdTokenAuthentication();
$authenticationConfiguration->setOdataType('#microsoft.graph.azureAdTokenAuthentication');
$authenticationConfiguration->setResourceId('api://authenticationeventsAPI.contoso.com/a13d0fc1-04ab-4ede-b215-63de0174cbb4');
$requestBody->setAuthenticationConfiguration($authenticationConfiguration);
$clientConfiguration = new CustomExtensionClientConfiguration();
$clientConfiguration->setTimeoutInMilliseconds(2000);
$clientConfiguration->setMaximumRetries(1);
$requestBody->setClientConfiguration($clientConfiguration);
$claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim1 = new OnTokenIssuanceStartReturnClaim();
$claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim1->setClaimIdInApiResponse('DateOfBirth');
$claimsForTokenConfigurationArray []= $claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim1;
$claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim2 = new OnTokenIssuanceStartReturnClaim();
$claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim2->setClaimIdInApiResponse('CustomRoles');
$claimsForTokenConfigurationArray []= $claimsForTokenConfigurationOnTokenIssuanceStartReturnClaim2;
$requestBody->setClaimsForTokenConfiguration($claimsForTokenConfigurationArray);
$result = $graphServiceClient->identity()->customAuthenticationExtensions()->post($requestBody)->wait();
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_body = OnTokenIssuanceStartCustomExtension(
odata_type = "#microsoft.graph.onTokenIssuanceStartCustomExtension",
display_name = "onTokenIssuanceStartCustomExtension",
description = "Fetch additional claims from custom user store",
endpoint_configuration = HttpRequestEndpoint(
odata_type = "#microsoft.graph.httpRequestEndpoint",
target_url = "https://authenticationeventsAPI.contoso.com",
),
authentication_configuration = AzureAdTokenAuthentication(
odata_type = "#microsoft.graph.azureAdTokenAuthentication",
resource_id = "api://authenticationeventsAPI.contoso.com/a13d0fc1-04ab-4ede-b215-63de0174cbb4",
),
client_configuration = CustomExtensionClientConfiguration(
timeout_in_milliseconds = 2000,
maximum_retries = 1,
),
claims_for_token_configuration = [
OnTokenIssuanceStartReturnClaim(
claim_id_in_api_response = "DateOfBirth",
),
OnTokenIssuanceStartReturnClaim(
claim_id_in_api_response = "CustomRoles",
),
]
)
result = await graph_client.identity.custom_authentication_extensions.post(body = request_body)
Record the id value of the created custom claims provider object. You'll use the value later in this tutorial in place of {customExtensionObjectId}.
2.2 Grant admin consent
After your custom authentication extension is created, open the Overview tab of the new custom authentication extension.
From the Overview page, select the Grant permission button to give admin consent to the registered app, which allows the custom authentication extension to authenticate to your API. The custom authentication extension uses client_credentials to authenticate to the Azure Function App using the Receive custom authentication extension HTTP requests permission.
The following screenshot shows how to grant permissions.
Step 3: Configure an OpenID Connect app to receive enriched tokens
To get a token and test the custom authentication extension, you can use the https://jwt.ms app. It's a Microsoft-owned web application that displays the decoded contents of a token (the contents of the token never leave your browser).
Follow these steps to register the jwt.ms web application:
Browse to Identity > Applications > Application registrations.
Select New registration.
Enter a Name for the application. For example, My Test application.
Under Supported account types, select Accounts in this organizational directory only.
In the Select a platform dropdown in Redirect URI, select Web and then enter https://jwt.ms in the URL text box.
Select Register to complete the app registration.
The following screenshot shows how to register the My Test application.
3.1 Get the application ID
In your app registration, under Overview, copy the Application (client) ID. The app ID is referred to as the {App_to_enrich_ID} in later steps. In Microsoft Graph, it's referenced by the appId propety.
3.2 Enable implicit flow
The jwt.ms test application uses the implicit flow. Enable implicit flow in your My Test application registration:
Under Manage, select Authentication.
Under Implicit grant and hybrid flows, select the ID tokens (used for implicit and hybrid flows) checkbox.
Select Save.
3.3 Enable your App for a claims mapping policy
A claims mapping policy is used to select which attributes returned from the custom authentication extension are mapped into the token. To allow tokens to be augmented, you must explicitly enable the application registration to accept mapped claims:
In your My Test application registration, under Manage, select Manifest.
In the manifest, locate the acceptMappedClaims attribute, and set the value to true.
Set the accessTokenAcceptedVersion to 2.
Select Save to save the changes.
The following JSON snippet demonstrates how to configure these properties.
Do not set acceptMappedClaims property to true for multi-tenant apps, which can allow malicious actors to create claims-mapping policies for your app. Instead configure a custom signing key.
Step 4: Assign a custom claims provider to your app
For tokens to be issued with claims incoming from the custom authentication extension, you must assign a custom claims provider to your application. This is based on the token audience, so the provider must be assigned to the client application to receive claims in an ID token, and to the resource application to receive claims in an access token. The custom claims provider relies on the custom authentication extension configured with the token issuance start event listener. You can choose whether all, or a subset of claims, from the custom claims provider are mapped into the token.
Follow these steps to connect the My Test application with your custom authentication extension:
Browse to Identity > Applications > Application registrations.
In the Overview page, under Managed application in local directory, select My Test application.
Under Manage, select Single sign-on.
Under Attributes & Claims, select Edit.
Expand the Advanced settings menu.
Select Configure against Custom claims provider.
Expand the Custom claims provider drop-down box, and select the Token issuance event you created earlier.
Select Save.
Next, assign the attributes from the custom claims provider, which should be issued into the token as claims:
Select Add new claim to add a new claim. Provide a name to the claim you want to be issued, for example dateOfBirth.
Under Source, select Attribute, and choose customClaimsProvider.DateOfBirth from the Source attribute drop-down box.
Select Save.
You can repeat this process to add the customClaimsProvider.customRoles, customClaimsProvider.apiVersion and customClaimsProvider.correlationId attributes.
First create an event listener to trigger a custom authentication extension for the My Test application using the token issuance start event.
Sign in to Graph Explorer using an account whose home tenant is the tenant you wish to manage your custom authentication extension in.
Run the following request. Replace {App_to_enrich_ID} with the app ID of My Test application recorded earlier. Replace {customExtensionObjectId} with the custom authentication extension ID recorded earlier.
You'll need the EventListener.ReadWrite.All delegated permission.
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new OnTokenIssuanceStartListener
{
OdataType = "#microsoft.graph.onTokenIssuanceStartListener",
Conditions = new AuthenticationConditions
{
Applications = new AuthenticationConditionsApplications
{
IncludeAllApplications = false,
IncludeApplications = new List<AuthenticationConditionApplication>
{
new AuthenticationConditionApplication
{
AppId = "a13d0fc1-04ab-4ede-b215-63de0174cbb4",
},
},
},
},
Priority = 500,
Handler = new OnTokenIssuanceStartCustomExtensionHandler
{
OdataType = "#microsoft.graph.onTokenIssuanceStartCustomExtensionHandler",
CustomExtension = new OnTokenIssuanceStartCustomExtension
{
Id = "6fc5012e-7665-43d6-9708-4370863f4e6e",
},
},
};
var result = await graphClient.Identity.AuthenticationEventListeners.PostAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new OnTokenIssuanceStartListener();
$requestBody->setOdataType('#microsoft.graph.onTokenIssuanceStartListener');
$conditions = new AuthenticationConditions();
$conditionsApplications = new AuthenticationConditionsApplications();
$conditionsApplications->setIncludeAllApplications(false);
$includeApplicationsAuthenticationConditionApplication1 = new AuthenticationConditionApplication();
$includeApplicationsAuthenticationConditionApplication1->setAppId('a13d0fc1-04ab-4ede-b215-63de0174cbb4');
$includeApplicationsArray []= $includeApplicationsAuthenticationConditionApplication1;
$conditionsApplications->setIncludeApplications($includeApplicationsArray);
$conditions->setApplications($conditionsApplications);
$requestBody->setConditions($conditions);
$requestBody->setPriority(500);
$handler = new OnTokenIssuanceStartCustomExtensionHandler();
$handler->setOdataType('#microsoft.graph.onTokenIssuanceStartCustomExtensionHandler');
$handlerCustomExtension = new OnTokenIssuanceStartCustomExtension();
$handlerCustomExtension->setId('6fc5012e-7665-43d6-9708-4370863f4e6e');
$handler->setCustomExtension($handlerCustomExtension);
$requestBody->setHandler($handler);
$result = $graphServiceClient->identity()->authenticationEventListeners()->post($requestBody)->wait();
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new ClaimsMappingPolicy
{
Definition = new List<string>
{
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}],\"ClaimsTransformation\":[{\"ID\":\"CreateTermsOfService\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"TOS\",\"TransformationClaimType\":\"createdClaim\"}]}]}}",
},
DisplayName = "Test1234",
};
var result = await graphClient.Policies.ClaimsMappingPolicies.PostAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new ClaimsMappingPolicy();
$requestBody->setDefinition(['{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}],\"ClaimsTransformation\":[{\"ID\":\"CreateTermsOfService\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"TOS\",\"TransformationClaimType\":\"createdClaim\"}]}]}}', ]);
$requestBody->setDisplayName('Test1234');
$result = $graphServiceClient->policies()->claimsMappingPolicies()->post($requestBody)->wait();
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_body = ClaimsMappingPolicy(
definition = [
"{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}],\"ClaimsTransformation\":[{\"ID\":\"CreateTermsOfService\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"TOS\",\"TransformationClaimType\":\"createdClaim\"}]}]}}",
]
display_name = "Test1234",
)
result = await graph_client.policies.claim_mapping_policies.post(body = request_body)
Record the ID generated in the response, later it's referred to as {claims_mapping_policy_ID}.
Get the service principal object ID:
Run the following request in Graph Explorer. Replace {App_to_enrich_ID} with the appId of My Test Application.
GET https://graph.microsoft.com/v1.0/servicePrincipals(appId='{App_to_enrich_ID}')
Record the value of id.
Assign the claims mapping policy to the service principal of My Test Application.
Run the following request in Graph Explorer. You'll need the Policy.ReadWrite.ApplicationConfiguration and Application.ReadWrite.All delegated permission.
POST https://graph.microsoft.com/v1.0/servicePrincipals/{test_App_Service_Principal_ObjectId}/claimsMappingPolicies/$ref
Content-type: application/json
{
"@odata.id": "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/{claims_mapping_policy_ID}"
}
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new Microsoft.Graph.Models.ReferenceCreate
{
OdataId = "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/cd3d9b57-0aee-4f25-8ee3-ac74ef5986a9",
};
await graphClient.ServicePrincipals["{servicePrincipal-id}"].ClaimsMappingPolicies.Ref.PostAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW VERSION OF THE SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new ReferenceCreate();
$requestBody->setOdataId('https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/cd3d9b57-0aee-4f25-8ee3-ac74ef5986a9');
$graphServiceClient->servicePrincipals()->byServicePrincipalId('servicePrincipal-id')->claimsMappingPolicies()->ref()->post($requestBody)->wait();
# THE PYTHON SDK IS IN PREVIEW. FOR NON-PRODUCTION USE ONLY
graph_client = GraphServiceClient(request_adapter)
request_body = ReferenceCreate(
odata_id = "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/cd3d9b57-0aee-4f25-8ee3-ac74ef5986a9",
)
await graph_client.service_principals.by_service_principal_id('servicePrincipal-id').claim_mapping_policies.ref.post(body = request_body)
Step 5: Protect your Azure Function
Microsoft Entra custom authentication extension uses server to server flow to obtain an access token that is sent in the HTTP Authorization header to your Azure function. When publishing your function to Azure, especially in a production environment, you need to validate the token sent in the authorization header.
To protect your Azure function, follow these steps to integrate Microsoft Entra authentication, for validating incoming tokens with your Azure Functions authentication events API application registration.
Note
If the Azure function app is hosted in a different Azure tenant than the tenant in which your custom authentication extension is registered, skip to using OpenID Connect identity provider step.
Navigate and select the function app you previously published.
Select Authentication in the menu on the left.
Select Add Identity provider.
Select Microsoft as the identity provider.
Under App registration->App registration type, select Pick an existing app registration in this directory and pick the Azure Functions authentication events API app registration you previously created when registering the custom claims provider.
Under Unauthenticated requests, select HTTP 401 Unauthorized as the identity provider.
Unselect the Token store option.
Select Add to add authentication to your Azure Function.
5.1 Using OpenID Connect identity provider
If you configured the Microsoft identity provider, skip this step. Otherwise, if the Azure Function is hosted under a different tenant than the tenant in which your custom authentication extension is registered, follow these steps to protect your function:
Sign in to the Azure portal, then navigate and select the function app you previously published.
Select Authentication in the menu on the left.
Select Add Identity provider.
Select OpenID Connect as the identity provider.
Provide a name, such as Contoso Microsoft Entra ID.
Under the Metadata entry, enter the following URL to the Document URL. Replace the {tenantId} with your Microsoft Entra tenant ID.
Under the App registration, enter the application ID (client ID) of the Azure Functions authentication events API app registration you created previously.
In the Microsoft Entra admin center:
Select the Azure Functions authentication events API app registration you created previously.
After logging in, you'll be presented with your decoded token at https://jwt.ms. Validate that the claims from the Azure Function are presented in the decoded token, for example, dateOfBirth.
Next steps
Learn how to configure a SAML application to receive tokens with claims sourced from an external store.