|
| 1 | +--- |
| 2 | +title: Custom claims provider reference |
| 3 | +titleSuffix: Microsoft identity platform |
| 4 | +description: Reference documentation for custom claims providers |
| 5 | +services: active-directory |
| 6 | +author: jassuri |
| 7 | +manager: CelesteDG |
| 8 | + |
| 9 | +ms.service: active-directory |
| 10 | +ms.subservice: develop |
| 11 | +ms.workload: identity |
| 12 | +ms.topic: conceptual |
| 13 | +ms.date: 03/06/2023 |
| 14 | +ms.author: davidmu |
| 15 | +ms.reviewer: jassuri |
| 16 | +ms.custom: aaddev |
| 17 | +#Customer intent: As a developer, I want to learn about custom authentication extensions so that I can augment tokens with claims from an external identity system or role management system. |
| 18 | +--- |
| 19 | + |
| 20 | +# Custom claims providers |
| 21 | + |
| 22 | +In this reference article, you can learn about the REST API schema and claims mapping policy structure for custom claim provider events. |
| 23 | + |
| 24 | +## Token issuance start event |
| 25 | + |
| 26 | +The custom claims provider token issuance event allows you to enrich or customize application tokens with information from external systems. This information that can't be stored as part of the user profile in Azure AD directory. |
| 27 | + |
| 28 | +### Component overview |
| 29 | + |
| 30 | +To set up and, integrate a custom extension with your application requires multiple components to be connected. The following diagram shows a high level view of the configuration points, and relationships that are created to implement a custom extension. |
| 31 | + |
| 32 | +:::image type="content" border="false" source="media/custom-extension-get-started/token-issuance-start-config.png" alt-text="Screenshot that shows the components to configure in Azure AD to set up and integrate a custom claims provider." lightbox="media/custom-extension-get-started/token-issuance-start-config.png"::: |
| 33 | + |
| 34 | +- You should have a **REST API endpoint** publicly available. In this diagram, it represented by Azure Function. The REST API generates and returns custom claims to the custom extension. It's associated with an Azure AD application registration. |
| 35 | +- You require to configure a **custom extension** in Azure AD, which is configured to connect to your API. |
| 36 | +- You require an **application** that receives the customized tokens. For example <https://jwt.ms> a Microsoft-owned web application that displays the decoded contents of a token. |
| 37 | +- The application, such as the <https://jwt.ms> must be registered into Azure AD using **app registration**. |
| 38 | +- You must create an association between your application and your custom extension. |
| 39 | +- You can optionally secure the Azure Function with an authentication provider, in this article we use your Azure AD. |
| 40 | + |
| 41 | +### REST API |
| 42 | + |
| 43 | +Your REST API endpoint is responsible for interfacing with downstream services. For example, databases, other REST APIs, LDAP directories, or any other stores that contain the attributes you'd like to add to the token configuration. |
| 44 | + |
| 45 | +The REST API returns an HTTP response to Azure AD containing the attributes. Attributes that return by your REST API aren't automatically added into a token. Instead, an application's claims mapping policy must be configured for any attribute to be included in the token. In Azure AD, a claims mapping policy modifies the claims emitted in tokens issued for specific applications. |
| 46 | + |
| 47 | +### REST API schema |
| 48 | + |
| 49 | +To develop your own REST API for the token issuance start event, use the following REST API data contract. The schema describes the contract to design the request and response handler. |
| 50 | + |
| 51 | +Your custom extension in Azure AD makes an HTTP call to your REST API with a JSON payload. The JSON payload contains user profile data, authentication context attributes, and information about the application the user wants to sign-in. The JSON attributes can be used to perform extra logic by your API. The request to your API is in the following format: |
| 52 | + |
| 53 | +```json |
| 54 | +{ |
| 55 | + "type": "microsoft.graph.authenticationEvent.tokenIssuanceStart", |
| 56 | + "source": "/tenants/<Your tenant GUID>/applications/<Your Test Application App Id>", |
| 57 | + "data": { |
| 58 | + "@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData", |
| 59 | + "tenantId": "<Your tenant GUID>", |
| 60 | + "authenticationEventListenerId": "<GUID>", |
| 61 | + "customAuthenticationExtensionId": "<Your custom extension ID>", |
| 62 | + "authenticationContext": { |
| 63 | + "correlationId": "<GUID>", |
| 64 | + "client": { |
| 65 | + "ip": "30.51.176.110", |
| 66 | + "locale": "en-us", |
| 67 | + "market": "en-us" |
| 68 | + }, |
| 69 | + "protocol": "OAUTH2.0", |
| 70 | + "clientServicePrincipal": { |
| 71 | + "id": "<Your Test Applications servicePrincipal objectId>", |
| 72 | + "appId": "<Your Test Application App Id>", |
| 73 | + "appDisplayName": "My Test application", |
| 74 | + "displayName": "My Test application" |
| 75 | + }, |
| 76 | + "resourceServicePrincipal": { |
| 77 | + "id": "<Your Test Applications servicePrincipal objectId>", |
| 78 | + "appId": "<Your Test Application App Id>", |
| 79 | + "appDisplayName": "My Test application", |
| 80 | + "displayName": "My Test application" |
| 81 | + }, |
| 82 | + "user": { |
| 83 | + "createdDateTime": "2016-03-01T15:23:40Z", |
| 84 | + "displayName": "Bob", |
| 85 | + "givenName": "Bob Smith", |
| 86 | + "id": "90847c2a-e29d-4d2f-9f54-c5b4d3f26471", |
| 87 | + |
| 88 | + "preferredLanguage": "en-us", |
| 89 | + "surname": "Smith", |
| 90 | + "userPrincipalName": "[email protected]", |
| 91 | + "userType": "Member" |
| 92 | + } |
| 93 | + } |
| 94 | + } |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +The REST API response format which Azure expects is in the following format, where the claims `DateOfBirth` and `CustomRoles` are returned to Azure: |
| 99 | + |
| 100 | +```json |
| 101 | +{ |
| 102 | + "data": { |
| 103 | + "@odata.type": "microsoft.graph.onTokenIssuanceStartResponseData", |
| 104 | + "actions": [ |
| 105 | + { |
| 106 | + "@odata.type": "microsoft.graph.tokenIssuanceStart.provideClaimsForToken", |
| 107 | + "claims": { |
| 108 | + "DateOfBirth": "01/01/2000", |
| 109 | + "CustomRoles": [ |
| 110 | + "Writer", |
| 111 | + "Editor" |
| 112 | + ] |
| 113 | + } |
| 114 | + } |
| 115 | + ] |
| 116 | + } |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +When a B2B user from Fabrikam organization authenticates to Contoso's organization, the request payload sent to the REST API has the `user` element in the following format: |
| 121 | + |
| 122 | +```json |
| 123 | +"user": { |
| 124 | + "companyName": "Fabrikam", |
| 125 | + "createdDateTime": "2022-07-15T00:00:00Z", |
| 126 | + "displayName": "John Wright", |
| 127 | + "id": "12345678-0000-0000-0000-000000000000", |
| 128 | + |
| 129 | + "preferredDataLocation": "EUR", |
| 130 | + "userPrincipalName": "johnwright_fabrikam.com#EXT#@contoso.onmicrosoft.com", |
| 131 | + "userType": "Guest" |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +### Supported data types |
| 136 | + |
| 137 | +The following table shows the data types supported by Custom claims providers for the token issuance start event: |
| 138 | + |
| 139 | +| Data type | Supported | |
| 140 | +|--------------|-----------| |
| 141 | +| String | True | |
| 142 | +| String array | True | |
| 143 | +| Boolean | False | |
| 144 | +| JSON | False | |
| 145 | + |
| 146 | +### Claims mapping policy |
| 147 | + |
| 148 | +In Azure AD, a claims mapping policy modifies the claims emitted in tokens issued for specific applications. It includes claims from your custom claims provider, and issuing them into the token. |
| 149 | + |
| 150 | +```json |
| 151 | +{ |
| 152 | + "ClaimsMappingPolicy": { |
| 153 | + "Version": 1, |
| 154 | + "IncludeBasicClaimSet": "true", |
| 155 | + "ClaimsSchema": [{ |
| 156 | + "Source": "CustomClaimsProvider", |
| 157 | + "ID": "dateOfBirth", |
| 158 | + "JwtClaimType": "birthdate" |
| 159 | + }, |
| 160 | + { |
| 161 | + "Source": "CustomClaimsProvider", |
| 162 | + "ID": "customRoles", |
| 163 | + "JwtClaimType": "my_roles" |
| 164 | + }, |
| 165 | + { |
| 166 | + "Source": "CustomClaimsProvider", |
| 167 | + "ID": "correlationId", |
| 168 | + "JwtClaimType": "correlation_Id" |
| 169 | + }, |
| 170 | + { |
| 171 | + "Source": "CustomClaimsProvider", |
| 172 | + "ID": "apiVersion", |
| 173 | + "JwtClaimType": "apiVersion" |
| 174 | + }, |
| 175 | + { |
| 176 | + "Value": "tokenaug_V2", |
| 177 | + "JwtClaimType": "policy_version" |
| 178 | + }] |
| 179 | + } |
| 180 | +} |
| 181 | +``` |
| 182 | + |
| 183 | +The `ClaimsSchema` element contains the list of claims to be mapped with the following attributes: |
| 184 | + |
| 185 | +- **Source** describes the source of the attribute, the `CustomClaimsProvider`. Note, the last element contains a fixed value with the policy version, for testing purposes. Thus, the `source` attribute is omitted. |
| 186 | + |
| 187 | +- **ID** is the name of the claims at it returns from the Azure Function you created. |
| 188 | + |
| 189 | + > [!IMPORTANT] |
| 190 | + > The ID attribute's value is case sensitive. Make sure you type the claim name exactly as it returned by the Azure Function. |
| 191 | +- **JwtClaimType** is an optional name of claim in the emitted token for OpenID Connect app. It allows you to provide a different name that returns in the JWT token. For example, if the API response has an `ID` value of `dateOfBirth`, it can be emitted as `birthdate` in the token. |
| 192 | + |
| 193 | +Once you create your claims mapping policy, the next step is to upload it to your Azure AD tenant. Use the following [claimsMappingPolicy](/graph/api/claimsmappingpolicy-post-claimsmappingpolicies) Graph API in your tenant. |
| 194 | + |
| 195 | +> [!IMPORTANT] |
| 196 | +> The **definition** element should be an array with a single string value. The string should be the stringified and escaped version of your claims mapping policy. You can use tools like [https://jsontostring.com/](https://jsontostring.com/) to stringify your claims mapping policy. |
| 197 | +
|
| 198 | +## Next steps |
| 199 | + |
| 200 | +- To learn how to [create and register a custom extension and API endpoint](custom-extension-get-started.md). |
| 201 | +- To learn how to customize the claims emitted in tokens for a specific application in their tenant using PowerShell, see [How to: Customize claims emitted in tokens for a specific app in a tenant](active-directory-claims-mapping.md) |
| 202 | +- To learn how to customize claims issued in the SAML token through the Azure portal, see [How to: Customize claims issued in the SAML token for enterprise applications](active-directory-saml-claims-customization.md) |
| 203 | +- To learn more about extension attributes, see [Using directory extension attributes in claims](active-directory-schema-extensions.md). |
0 commit comments