|
| 1 | +--- |
| 2 | +title: Extend API-driven provisioning to sync custom attributes |
| 3 | +description: Learn how to extend API-driven inbound provisioning to sync custom attributes. |
| 4 | +services: active-directory |
| 5 | +author: jenniferf-skc |
| 6 | +manager: amycolannino |
| 7 | +ms.service: active-directory |
| 8 | +ms.subservice: app-provisioning |
| 9 | +ms.workload: identity |
| 10 | +ms.topic: how-to |
| 11 | +ms.date: 07/24/2023 |
| 12 | +ms.author: jfields |
| 13 | +ms.reviewer: cmmdesai |
| 14 | +--- |
| 15 | + |
| 16 | +# Extend API-driven provisioning to sync custom attributes (Public preview) |
| 17 | + |
| 18 | +By default, API-driven provisioning apps support processing attributes that are part of the standard SCIM Core User and Enterprise User schema. Your system of record may have custom attributes that you may want to include as part of API-driven provisioning. This advanced tutorial describes how to extend your API-driven provisioning app to process additional custom attributes. |
| 19 | + |
| 20 | +> [!NOTE] |
| 21 | +> Before trying this advanced scenario, we recommend verifying that your out-of-the-box provisioning app configuration works as expected using one of the following API clients [Graph Explorer](inbound-provisioning-api-graph-explorer.md), [cURL](inbound-provisioning-api-curl-tutorial.md) or [Postman](inbound-provisioning-api-postman.md). |
| 22 | +
|
| 23 | +## Example scenario |
| 24 | + |
| 25 | +You have configured API-driven provisioning app. You're provisioning app is successfully consuming the attributes that are part of the standard SCIM Core User and Enterprise User schema and provisioning users in Azure AD. You now want to send two custom attributes `HireDate` and `JobCode` from your HR system to the inbound provisioning API endpoint. You'd like to map these two custom attributes to Azure AD attributes `employeeHireDate` and `jobTitle`. |
| 26 | + |
| 27 | +## Step 1 - Extend the provisioning app schema |
| 28 | + |
| 29 | +In this step, we'll add the two attributes "HireDate" and "JobCode" that are not part of the standard SCIM schema to the provisioning app and use them in the provisioning data flow. |
| 30 | + |
| 31 | +1. Log in to Microsoft Entra portal with application administrator role. |
| 32 | +1. Go to **Enterprise applications** and open your API-driven provisioning app. |
| 33 | +1. Open the **Provisioning** blade. |
| 34 | +1. Click on the **Edit Provisioning** button. |
| 35 | +1. Expand the **Mappings** section and click on the attribute mapping link. <br> |
| 36 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/edit-attribute-mapping.png" alt-text="Screenshot of edit attribute mapping." lightbox="./media/inbound-provisioning-api-custom-attributes/edit-attribute-mapping.png"::: |
| 37 | +1. Scroll down the **Attribute Mappings** page. Select **Show advanced options** and click on the **Edit attribute list for API** link. |
| 38 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/edit-api-attribute-list.png" alt-text="Screenshot of edit API attribute list." lightbox="./media/inbound-provisioning-api-custom-attributes/edit-api-attribute-list.png"::: |
| 39 | +1. Scroll down to the end of the **Edit Attribute List** page. |
| 40 | +1. Add the following two attributes to the list as SCIM schema extensions. You can use your own SCIM schema namespace. <br> |
| 41 | + `urn:ietf:params:scim:schemas:extension:contoso:1.0:User:HireDate` <br> |
| 42 | + `urn:ietf:params:scim:schemas:extension:contoso:1.0:User:JobCode` <br> |
| 43 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/add-custom-attributes.png" alt-text="Screenshot of adding custom attributes." lightbox="./media/inbound-provisioning-api-custom-attributes/add-custom-attributes.png"::: |
| 44 | +1. **Save** your changes |
| 45 | + |
| 46 | +> [!NOTE] |
| 47 | +> If you'd like to add only a few additional attributes to the provisioning app, use Microsoft Entra Portal to extend the schema. If you'd like to add more custom attributes (let's say 20+ attributes), then we recommend using the [`UpdateSchema` mode of the CSV2SCIM PowerShell script](inbound-provisioning-api-powershell.md#extending-provisioning-job-schema) which automates the above manual process. |
| 48 | +
|
| 49 | +## Step 2 - Map the custom attributes |
| 50 | + |
| 51 | +Let's now add these extensions to the provisioning app attribute mapping. |
| 52 | + |
| 53 | +1. Click on the **Add New Mapping** link on the **Attribute mapping** page. |
| 54 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/add-new-mapping.png" alt-text="Screenshot of add new mapping." lightbox="./media/inbound-provisioning-api-custom-attributes/add-new-mapping.png"::: |
| 55 | +1. Map the `urn:ietf:params:scim:schemas:extension:contoso:1.0:User:HireDate` attribute to `employeeHireDate`. Click **OK**. <br> |
| 56 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/hire-date-mapping.png" alt-text="Screenshot of hire date mapping." lightbox="./media/inbound-provisioning-api-custom-attributes/hire-date-mapping.png"::: |
| 57 | +1. Next, select the existing mapping for `title` and click on it to edit the mapping. |
| 58 | +1. Edit the attribute mapping to an expression that will include the `urn:ietf:params:scim:schemas:extension:contoso:1.0:User:JobCode` as part of the `jobTitle` Azure AD attribute. |
| 59 | + ``` |
| 60 | + Join("", [title], "(", [urn:ietf:params:scim:schemas:extension:contoso:1.0:User:JobCode], ")") |
| 61 | + ``` |
| 62 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/job-title-mapping.png" alt-text="Screenshot of job title mapping." lightbox="./media/inbound-provisioning-api-custom-attributes/job-title-mapping.png"::: |
| 63 | + |
| 64 | + With this expression mapping, if the `title` is "Tour Lead" and `JobCode`is "TL-1001", then the Azure AD attribute `jobTitle` will be set to "Tour Lead (TL-1001)". |
| 65 | +1. Save the attribute mappings. |
| 66 | + |
| 67 | +## Step 3 - Upload bulk request with custom attributes |
| 68 | + |
| 69 | +1. Open your API client (Graph Explorer / Postman / cURL). |
| 70 | +1. Copy-paste the [bulk request with custom attributes](#bulk-request-with-custom-attributes). |
| 71 | +1. Send the bulk request to your provisioning API endpoint URL. <br> |
| 72 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/upload-bulk-request.png" alt-text="Screenshot of bulk upload request." lightbox="./media/inbound-provisioning-api-custom-attributes/upload-bulk-request.png"::: |
| 73 | +1. After some time, you can check the provisioning logs to verify the attribute change. <br> |
| 74 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/verify-provisioning-logs.png" alt-text="Screenshot of provisioning logs." lightbox="./media/inbound-provisioning-api-custom-attributes/verify-provisioning-logs.png"::: |
| 75 | +1. You can also verify the change in the Azure AD user profile. The value for `Employee hire date` reflects your tenant time zone. <br> |
| 76 | + :::image type="content" border="true" source="./media/inbound-provisioning-api-custom-attributes/verify-user-profile.png" alt-text="Screenshot of user profile." lightbox="./media/inbound-provisioning-api-custom-attributes/verify-user-profile.png"::: |
| 77 | + |
| 78 | +## Appendix |
| 79 | + |
| 80 | +### Bulk request with custom attributes |
| 81 | + |
| 82 | +The bulk request includes the custom attributes configured in the steps above. |
| 83 | + |
| 84 | +**Request body** |
| 85 | +```http |
| 86 | +{ |
| 87 | + "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"], |
| 88 | + "Operations": [ |
| 89 | + { |
| 90 | + "method": "POST", |
| 91 | + "bulkId": "701984", |
| 92 | + "path": "/Users", |
| 93 | + "data": { |
| 94 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", |
| 95 | + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", |
| 96 | + "urn:ietf:params:scim:schemas:extension:contoso:1.0:User"], |
| 97 | + "externalId": "701984", |
| 98 | + |
| 99 | + "name": { |
| 100 | + "formatted": "Ms. Barbara J Jensen, III", |
| 101 | + "familyName": "Jensen", |
| 102 | + "givenName": "Barbara", |
| 103 | + "middleName": "Jane", |
| 104 | + "honorificPrefix": "Ms.", |
| 105 | + "honorificSuffix": "III" |
| 106 | + }, |
| 107 | + "displayName": "Babs Jensen", |
| 108 | + "nickName": "Babs", |
| 109 | + "emails": [ |
| 110 | + { |
| 111 | + |
| 112 | + "type": "work", |
| 113 | + "primary": true |
| 114 | + } |
| 115 | + ], |
| 116 | + "addresses": [ |
| 117 | + { |
| 118 | + "type": "work", |
| 119 | + "streetAddress": "234300 Universal City Plaza", |
| 120 | + "locality": "Hollywood", |
| 121 | + "region": "CA", |
| 122 | + "postalCode": "91608", |
| 123 | + "country": "USA", |
| 124 | + "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA", |
| 125 | + "primary": true |
| 126 | + } |
| 127 | + ], |
| 128 | + "phoneNumbers": [ |
| 129 | + { |
| 130 | + "value": "555-555-5555", |
| 131 | + "type": "work" |
| 132 | + } |
| 133 | + ], |
| 134 | + "userType": "Employee", |
| 135 | + "title": "Tour Guide", |
| 136 | + "preferredLanguage": "en-US", |
| 137 | + "locale": "en-US", |
| 138 | + "timezone": "America/Los_Angeles", |
| 139 | + "active":true, |
| 140 | + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { |
| 141 | + "employeeNumber": "701984", |
| 142 | + "costCenter": "4130", |
| 143 | + "organization": "Universal Studios", |
| 144 | + "division": "Theme Park", |
| 145 | + "department": "Tour Operations", |
| 146 | + "manager": { |
| 147 | + "value": "89607", |
| 148 | + "displayName": "John Smith" |
| 149 | + } |
| 150 | + }, |
| 151 | + "urn:ietf:params:scim:schemas:extension:contoso:1.0:User": { |
| 152 | + "HireDate": "2021-05-01T00:00:00-05:00", |
| 153 | + "JobCode": "TG-1001" |
| 154 | + } |
| 155 | + } |
| 156 | + }, |
| 157 | + { |
| 158 | + "method": "POST", |
| 159 | + "bulkId": "701985", |
| 160 | + "path": "/Users", |
| 161 | + "data": { |
| 162 | + "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", |
| 163 | + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", |
| 164 | + "urn:ietf:params:scim:schemas:extension:contoso:1.0:User"], |
| 165 | + "externalId": "701985", |
| 166 | + |
| 167 | + "name": { |
| 168 | + "formatted": "Ms. Kathy J Jensen, III", |
| 169 | + "familyName": "Jensen", |
| 170 | + "givenName": "Kathy", |
| 171 | + "middleName": "Jane", |
| 172 | + "honorificPrefix": "Ms.", |
| 173 | + "honorificSuffix": "III" |
| 174 | + }, |
| 175 | + "displayName": "Kathy Jensen", |
| 176 | + "nickName": "Kathy", |
| 177 | + "emails": [ |
| 178 | + { |
| 179 | + |
| 180 | + "type": "work", |
| 181 | + "primary": true |
| 182 | + } |
| 183 | + ], |
| 184 | + "addresses": [ |
| 185 | + { |
| 186 | + "type": "work", |
| 187 | + "streetAddress": "100 Oracle City Plaza", |
| 188 | + "locality": "Hollywood", |
| 189 | + "region": "CA", |
| 190 | + "postalCode": "91618", |
| 191 | + "country": "USA", |
| 192 | + "formatted": "100 Oracle City Plaza\nHollywood, CA 91618 USA", |
| 193 | + "primary": true |
| 194 | + } |
| 195 | + ], |
| 196 | + "phoneNumbers": [ |
| 197 | + { |
| 198 | + "value": "555-555-5545", |
| 199 | + "type": "work" |
| 200 | + } |
| 201 | + ], |
| 202 | + "userType": "Employee", |
| 203 | + "title": "Tour Lead", |
| 204 | + "preferredLanguage": "en-US", |
| 205 | + "locale": "en-US", |
| 206 | + "timezone": "America/Los_Angeles", |
| 207 | + "active":true, |
| 208 | + "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { |
| 209 | + "employeeNumber": "701984", |
| 210 | + "costCenter": "4130", |
| 211 | + "organization": "Universal Studios", |
| 212 | + "division": "Theme Park", |
| 213 | + "department": "Tour Operations", |
| 214 | + "manager": { |
| 215 | + "value": "701984", |
| 216 | + "displayName": "Barbara Jensen" |
| 217 | + } |
| 218 | + }, |
| 219 | + "urn:ietf:params:scim:schemas:extension:contoso:1.0:User": { |
| 220 | + "HireDate": "2022-07-15T00:00:00-05:00", |
| 221 | + "JobCode": "TL-1003" |
| 222 | + } |
| 223 | + } |
| 224 | + } |
| 225 | +], |
| 226 | + "failOnErrors": null |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | +## Next steps |
| 231 | + |
| 232 | +- [Troubleshoot issues with the inbound provisioning API](inbound-provisioning-api-issues.md) |
| 233 | +- [Frequently asked questions about API-driven inbound provisioning](inbound-provisioning-api-faqs.md) |
| 234 | +- [Quick start using PowerShell](inbound-provisioning-api-powershell.md) |
| 235 | +- [Quick start using Azure Logic Apps](inbound-provisioning-api-logic-apps.md) |
0 commit comments