This is the final post in a series detailing using PowerShell to leverage the Azure AD Graph API. For those catching up it started here introducing using PowerShell to access the Azure AD via the Graph API, licensing users in Azure AD via Powershell and the Graph API, and returning all objects using paging via Powershell and the Graph API.
In this post I show how to;
- enumerate objects from Azure AD via Powershell and the Graph API, and set a delta change cookie
- enumerate changes in Azure AD since the last query
- return objects that have changed since the last query
- return just the changed attributes on objects that have changed since the last query
- get a differential sync from now delta change link
Searching through MSDN and other resources working this out I somehow stumbled upon a reference to changes in the API that detail the search filters. v1.5 and later of the API requires filters using the context ‘Microsoft.DirectoryServices.User|Group|Contact’ etc instead of ‘Microsoft.WindowsAzure.ActiveDirectory.User|Group|Contact’ which you’ll find in the few examples around. If you don’t want to return all these object types update the filter on line 21 in the script below.
Here is the script to return all Users, Groups and Contacts from the tenant along with all the other options I detail in this post. Update the following for your tenant;
- line 6 for your tenant URI
- line 10 for your account in the tenant
- line 11 for the password associated with your account from line 10
Here is a sample output showing the Users, Groups, Contacts and DirectoryLinkChange objects. Note: if you have a large tenant that has been in place for a period of time it may take a while to enumerate. In this instance you can use the Differential Sync from now option. More on that later.
https://dl.dropboxusercontent.com/u/76015/BlogImages/DifferentialQuery/FirstDQRun.png
Running the query again using the Differential DeltaLink from the first run now returns no results. This is as expected as no changes have been made in the tenant on the objects in our query.
https://dl.dropboxusercontent.com/u/76015/BlogImages/DifferentialQuery/SecondDQRun.png
Now if I make a change in the tenant and run the query again using the Differential DeltaLink I get 1 result. And I get the full object.
https://dl.dropboxusercontent.com/u/76015/BlogImages/DifferentialQuery/ThirdDQRun.png
What if I just wanted to know the change that was made?
If we add ‘&ocp-aad-dq-include-only-changed-properties=true’ to the URI that’s exactly what we get. The object and what changed. In my case the Department attribute.
https://dl.dropboxusercontent.com/u/76015/BlogImages/DifferentialQuery/ForthDQRun.png
Finally as alluded to earlier there is the Differential Sync from now option. Very useful on large tenants where you can query and get all users, contacts, groups etc without using differential sync, then get the Differential Delta token for future sync queries. So I’ve used the same URI that I used as the beginning of this blog post but in the header specified ‘ocp-aad-dq-include-only-delta-token’ = “true” and as you can see I returned no results but I got the important Differential Query DeltaLink.
https://dl.dropboxusercontent.com/u/76015/BlogImages/DifferentialQuery/FifthDQRun.png
Summary
Using Powershell we can leverage the Azure AD Graph RestAPI and use the Differential Sync functions to efficiently query Azure AD for changes rather than needing to enumerate an entire tenant each time. Brilliant.
Follow Darren on Twitter @darrenjrobinson
Hello Darren,
I tried this script but I am receiving below error message.
Exception calling “AcquireToken” with “3” argument(s): “AADSTS7000218: The request body must contain the following parameter: ‘client_assertion’ or ‘client_secret’.
Trace ID: 661f5dd1-d985-48ce-8128-dc3918f34500
Correlation ID: bee9612a-1532-4daf-8307-34cab68a6201
Timestamp: 2019-08-12 06:58:43Z”
Please guide me if I am missing anything.
Regards,
Sachin