User directory: Microsoft Graph

You can synchronize your users and groups via Microsoft Graph API. To enable the sync, you need to complete steps both in Microsoft Entra ID and in Haiilo's Administration.

When syncing a user directory, users and groups are considered separately in the sync. Groups are synced first, followed by users. Users can only be added to groups synced in the first step. However, all users matching the user filters are synced, regardless of whether they belong to the groups synced in the group sync.

Please complete the app registration in Microsoft Entra ID as detailed in the Setting up Microsoft authentication article before proceeding with this tutorial.

Add API permissions in Microsoft

You need admin rights in your Microsoft Entra ID account to complete the configuration.

  1. Log in to the Microsoft Azure Platform.
  2. Go to Microsoft Entra ID > App registrations > select the app that you created when setting up Microsoft authentication for Haiilo
  3. Go to API permissions
  4. Select Add permissions > Microsoft Graph > Application permissions
  5. Add the following API permissions:
    • Group.Read.All
    • User.Read.All
  6. Select Grant admin consent for app_name for the added permissions and ensure the status for all permissions is marked Granted for your_tenant.

Set up a new user directory in Haiilo

You need "Manage user directories" permission to set up a Microsoft Graph user directory in Haiilo.

  1. In Haiilo, go to Administration > User directories
  2. Select Create user directory
  3. Enter a name
  4. Choose the type: Microsoft Graph
  5. Check Active, if this new user directory should be activated directly

Fill out the fields on each tab as detailed below.

Connection

  1. Input the Application (client) ID that you copied from Microsoft Entra ID into the Client ID field
  2. Input the Client Secret Value that you copied from Microsoft Entra ID into the Client Secret field
  3. Input the Directory (tenant) ID that you copied from Microsoft Entra ID into the Tenant ID field
  4. Select Test connection to verify the connection is established

User

  1. User filter: Define filters to synchronize only certain users. You can use the standard Microsoft Graph filters, e.g., startsWith(displayName,'Jane').
  2. Local user filter: The local user filter acts just like the normal user filter but isn't part of the query to the MS Graph API but will be executed on the Haiilo backend on the received response. This allows for filtering by the 'user filter' in the 1st stage and then filtering further by the 'local user filter' using expressions that MS Graph doesn't support.
  3. Remove local groups: Check if you want to remove the synced users from any local groups they've been manually added to.
  4. Remove other directory groups: Check if you want to remove the synced users from any other user directory groups they've been manually added to.
  5. Sync managers: Check if you want users' managers and teams to be visible on their profiles.
  6. Username: Enter the attribute for username. We recommend using mail or userPrincipalName.
  7. You can also synchronize additional profile fields. Profile field mapping can be complex for MS Graph API because the API responds with JSON objects that can contain nested data.

Groups

  1. To synchronize groups from Microsoft Graph, check Synchronize groups.
  2. Group filter: Define filters to synchronize only certain groups. You can use the standard Microsoft Graph filters, e.g., startsWith(displayName, 'Haiilo')
  3. Users from groups only: Check if you only want to sync users that are part of a synchronized group. Enabling this means that only the users matching the User filter that also belong to a group synced in the group sync will be synced.
  4. Preserve groups: If Synchronize groups is disabled, you can check this field to preserve any previously synced groups for this specific user directory. This way, you can freeze the previously synced groups. If left unchecked, any previously synced groups and their memberships will be removed in the next sync.

Synchronization

  1. Page size: Defines how many items are synchronized per query. We recommend not setting the page size to a value higher than 120, as Microsoft states this as the limit in their documentation. However, they also say that the value could be even lower depending on the query.
  2. Activation: If checked, new and restored users are activated during synchronization. Otherwise, you have to manually set the status of the users to Active in the user management.
  3. Orphaned users: Choose what happens to users that currently exist as active users on Haiilo, but no longer exist in the user directory. If you choose Ignore, they will remain unchanged.
  4. Restore users: If checked, a user who has been deactivated or deleted from Haiilo but is present again in the user directory during the sync will be reactivated. It's not possible to restore anonymized users. A previously anonymized user can only be created as a new user.

Scheduling

  1. Choose the synchronization frequency. If you choose Disabled, you run the sync manually.

Additional information on mapping profile fields

The profile field mapping of a user can be somewhat complex because the MS Graph API responds with JSON objects that can contain nested data. This requires the use of a more complex field address syntax. We chose JSONPath, which allows access to nested or indexed properties and also the use of predicates, which are useful for extension selection.

MS Graph also requires that you specify in the query which properties the call should return. This is done by passing a list of fields in the $select or $expand parameters. A simple field name is automatically inserted verbatim into the $select clause of the MS Graph API query. The new syntax accepts the select/expand clause as an optional second part of the expression. The previous simple field syntax is still valid and can also be used.

For the additional field mapping, the syntax is as follows:

<jsonpath>[:select/expand- clause]

Please pay attention to the following syntax:

  • The JSONPath must start with $. to be recognized as new JSONPath syntax
  • If the JSONPath contains a colon, the colon must be masked with a backslash
  • If the JSONPath selects more than one entry, only the first one is returned
  • The selected value is converted to a string
  • A missing value leads to an empty profile field

The path may optionally be followed by a colon (the colon must not be masked with a backslash here) and the select/expand clause corresponding to an entry of the $select or $expand parameter above. Only if the value is extensions, the query parameter $expand=extensions is added. Any other value is interpreted as an entry for the $select field list. It is recommended to configure the select/expand clause to ensure that the API response contains the required field.

Examples of syntax for profile fields assignment

  • $.aboutMe:aboutMe
    • This expression adds the $select=aboutMe parameter to the query. The JSONPath part will select the aboutMe property from the query result. This expression is equivalent to the aboutMe simple field expression.
  • $.employeeOrgData.division:employeeOrgData
    • This expression adds the $select=employeeOrgData parameter to the query. The JSONPath part selects the nested property division of the root employeeOrgData property. This expression has no equivalent in a simple field expression because it is not possible to select nested properties in this way.
  • $.extensions[?(@.id=='com.haiilo')].nested.prop1:extensions
    • This expression adds the $expand=extensions parameter to the query. The JSONPath part selects the first extension inside the root object, which has a property id with value com.haiilo. From this extension, the nested property nested.prop1 is selected.

The API response is not known until the synchronization job is executed, so it is not known what a valid JSONPath expression actually selects. We currently recommend administrators to query the Microsoft Graph API manually with a tool like Postman, then copy the JSON response into a JSONPath evaluation tool and find out what the expression returns.

Was this article helpful?