If you have a Microsoft 365 subscription, your users are defined in the Azure Active Directory (AAD). The AD infrastructure can be hybrid, which means it is shared/synced with your on-premise AD, but, in some cases, there is no longer an on-premise AD (or infrastructure). When it came to users and authentication, LDAP was the protocol for on-premise integration, but in Microsoft 365 we can leverage the functions of the MS Graph API. The XQTING integration engine (XQi Engine) can help you to quickly and easily synchronize the users in the AAD with any other on-premise or cloud solution, and as such deliver a series of processes for user onboarding that saves time (and avoid errors, or “forgottens”) for your administrators.
Note: the Azure AD Graph API is planned to retire in the near feature in favour of the MS Graph API which delivers a similar set of functionality.
In our example, we’ll use our Microsoft 365 XQTING directory, and, synchronize all users to our Splitvice instance (which has a public REST API as well) where we keep our planning. Users will be added and invited automatically when the administrator creates an AAD account for them.
This example illustrates only one particular use case, and, in a similar way, with addition of a limited lines of code, alternative use cases can be implemented:
- Synchronizing between multiple Microsoft 365 tenants (!)
- Synchronizing from one source to multiple destinations, so distributing user changes to multiple other applications in your organisation
- Consolidating information from multiple sources, to one target. For example, when a user is added, you might need to get additional information from a second source to update the information in the target destination
- It doesn’t only work for users, it can actually be used for any entity/object that is in the MS Graph API, which, is in essence all the information available in your Microsoft 365 tenant.
How to synchronize using the XQi Engine
In a previous article (read it here), we already described the functions of the XQi Engine in an API driven world. To synchronize two applications by means of their APIs, there are in general two ways:
- the “master” (the one that holds the data that must be fetched and synced with other applications) generates a request to a registered URL as means of notification (a webhook, or also sometimes called a subscription) and this is handled by the engine, which transforms the data and then calls another API
- both solutions only have an API to fetch data but they do not generate notifications. A synchronisation relies on regularly getting the information from the master, and then transform the data and call the other API
Both scenarios are easy to solve with the XQi Engine:
- in case of a notification, the XQi Engine can act as webserver endpoint to handle the notification. Data is transformed in the script and the other application is informed using the HTTP client, or database insert, or whatever is needed to add users to it (not everything is REST API already)
- in the second scenario, the XQi Engine has a built-in timer module that will generate a timer notification on a specific schedule. This notification can be handled in the script to fetch the master data. Once that is done, a script can be used to transform the data and send it to the target application. This is a so called a “polling” solution, and is less optimal than the first one because many of these gets will have no changed data… however, sometimes there is no other way.
For synchronizing users, it is possible to work both ways with MS Graph. However, this article will illustrate the second scenario which is the most common for many APIs (also for MS Graph, because there is only a limited set of notifications available in the MS Graph API). In our next post, we will cover how to handle the notifications.
Getting users from the AAD
To fetch the user information on a regular base from AAD, we need to configure the timer module and we must register the XQi Engine as an application in the AAD. A detailed step-by-step procedure can be found here: https://xqting.wordpress.com/2020/06/24/registering-the-xqi-engine-in-microsoft-365-to-use-ms-graph-api/. Make sure your application has the necessary API permissions to call the users function. All information about the function and the required permissions can be found here: https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http. If it is your intention to work with the AD objects, probably the Directory.Read.All permission might be the best option.
In the XQi Engine, configuring the timer and msGraph module is done in the engine.js startup configuration script. We set a timer to trigger every five minutes, and the msGraph information can be found in the AAD registration.
Next, our process script can be built to handle the timer event, fetch the msGraph data and (temporarily) store the result.
Getting Splitvice users
Even though we could just “create” every user again and again (and count on the API we call to return an error if the user already exists), this is not a nice way of working, because it generates a massive amount of errors or warnings, not only in the XQi Engine, but also in the application that we are calling. A better and nicer way is to fetch the users from the other party (the Splitvice platform in this case) and check which one exist, and which one must be created.
To call the Splitvice API, we need a “simple” HTTPS client module that uses an API key created in Splitvice for authentication.
Once we have the API key, configuring the HTTP client module is easy:
This enables us to extend our process to fetch all Splitvice users as soon as we have fetched the MS Graph users:
Comparing and creating new users
With the above two arrays of information, we can easily compare the data of each of the applications and create new users using the httpClient.post(…) command on the splitvice http client module.
However, if you have done this type of integration, you know that in reality, user data doesn’t really change that often. How many users does your company add on a daily basis? Most of the work done will be superfluous, so we’d better optimize the solution to avoid too many useless API calls.
The simplest way to avoid many unnecessary API calls is to increase the timer interval, however, this has often the (undesired) side-effect that the synchronization is perceived as “slow”, and, users have to wait a ” long time” to have their other accounts. So this might not be the best solution
Another simple way to avoid unnecessary API calls, is by storing the MS Graph information in the local storage of the engine. For example, to store a (filtered? compacted?) list of users, you can can do like this:
The next time you get the users from the msGraph module, you can compare the stored changes with the newly fetched items, and, if no changes are detected, the process can be terminated immediately. This doesn’t avoid all useless API calls, but is a good trade-off between the number of API calls and the speed of synchronization.