How to create a PowerShell FIM/MIM Management Agent for AzureAD Groups using Differential Sync and Paged Imports


I’ve been working on a project where I must have visibility of a large number of Azure AD Groups into Microsoft Identity Manager.

In order to make this efficient I need to use the Differential Query function of the AzureAD Graph API. I’ve detailed that before in this post How to create an AzureAD Microsoft Identity Manager Management Agent using the MS GraphAPI and Differential Queries. Due to the number of groups and the number of members in the Azure AD Groups I needed to implement Paged Imports on my favourite PowerShell Management Agent (Granfeldt PowerShell MA). I’ve previously detailed that before too here How to configure Paged Imports on the Granfeldt FIM/MIM PowerShell Management Agent.

This post details using these concepts together specifically for AzureAD Groups.


Read the two posts linked to above. They will detail Differential Queries and Paged Imports. My solution also utilises another of my favourite PowerShell Modules. The Lithnet MIIS Automation PowerShell Module. Download and install that on the MIM Sync Server where you be creating the MA.


Now that you’re up to speed, all you need to do is create your Granfeldt PowerShell Management Agent. That’s also covered in the post linked above  How to create an AzureAD Microsoft Identity Manager Management Agent using the MS GraphAPI and Differential Queries.

What you need is the Schema and Import PowerShell Scripts. Here they are.


Two object classes on the MA as we need to have users that are members of the groups on the same MA as membership is a reference attribute. When you bring through the Groups into the MetaVerse and assuming you have an Azure AD Users MA using the same anchor attribute then you’ll get the reference link for the members and their full object details.


Here is my PSMA Import.ps1 that performs what is described in the overview. Enumerate AzureAD for Groups, import the active ones along with group membership.


This is one solution for managing a large number of Azure AD Groups with large memberships via a PS MA with paged imports showing progress thanks to differential sync which then allows for subsequent quick delta-sync run profiles.

I’m sure this will help someone else. Enjoy.

Follow Darren on Twitter @darrenjrobinson

How to create an AzureAD Microsoft Identity Manager Management Agent using the MS GraphAPI and Differential Queries


In August 2016 I wrote this post on how to use PowerShell to leverage the Microsoft GraphAPI and use Differential Queries. The premise behind that post was I required a Microsoft Identity Manager Management Agent to synchronize identity information from AzureAD into Microsoft Identity Manager. However the environment it was intended for has a large AzureAD implementation and performing a Full Sync every-time is just to time consuming. Even more so with this limitation that still exists today in MIM 2016 with SP1.

In this blog post I’ll detail how to implement a PowerShell Management Agent for FIM/MIM to use the MS GraphAPI to synchronize objects into FIM/MIM, supporting Delta and Full Synchronization run profiles. I’m also using my favourite PowerShell Management Agent, the Granfeldt PowerShell Management Agent.


I’m using the ADAL helper library from the AzureADPreview PowerShell Module. Install that module on you MIM Sync Server via PowerShell (WMF5 or later) using the PowerShell command;

Install-Module AzureADPreview

Getting Started with the Granfeldt PowerShell Management Agent

If you don’t already have it, what are you waiting for. Go get it from here. Søren’s documentation is pretty good but does assume you have a working knowledge of FIM/MIM and this blog post is no different.

Three items I had to work out that I’ll save you the pain of are;

  • You must have a Password.ps1 file. Even though we’re not doing password management on this MA, the PS MA configuration requires a file for this field. The .ps1 doesn’t need to have any logic/script inside it. It just needs to be present
  • The credentials you give the MA to run this MA are the credentials for the account that has permissions to the AzureAD/Office365 Tenant. Just a normal account is enough to enumerate it, but you’ll need additional permissions if you intend to write-back to AzureAD.
  • The path to the scripts in the PS MA Config must not contain spaces and be in old-skool 8.3 format. I’ve chosen to store my scripts in an appropriately named subdirectory under the MIM Extensions directory. Tip: from a command shell use dir /x to get the 8.3 directory format name. Mine looks like C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\AzureAD


My Schema is based around enumerating and managing users from AzureAD. You’ll need to create a number of corresponding attributes in the Metaverse Schema on the Person ObjectType to flow the attributes into. Use the Schema info below for a base set of attributes that will get you started. You can add more as required. I’ve prefixed most of them with AAD for my implementation.

If you want to manage Groups or Contacts or a combination of object types, you will need to update the Schema.ps1 script accordingly.


The logic that the Import.ps1 implements is the same as detailed here in my post using Differential Queries. Essentially, perform a full import and create a file with the cookie/watermark. Allow Delta Sync run profiles to be performed by requesting the GraphAPI to return only changes since the cookie/watermark.

You’ll need to update the script for your AzureAD Tenant name on Line 28. Also the path to where the cookie file will go and the debug file if your path is different to mine. Lines 11, 46 and 47.

Importing of the attributes is based around the names in the Schema.ps1 scripts. Any changes you made there will need to be reflected in the import.ps1.

Password Script (password.ps1)

Empty as not implemented


Empty as not implemented in this example. If you are going to write information back to AzureAD you’ll need to put the appropriate logic into this script.

Management Agent Configuration

With the Granfeldt PowerShell Management Agent installed on your FIM/MIM Synchronisation Server, in the Synchronisation Server Manager select Create Management Agent and choose “PowerShell” from the list of Management Agents to create.

As this example is for Users, I’ve named my MA accordingly.

As per the tips above, the format for the script paths must be without spaces etc. I’m using 8.3 format and I’m using an Office 365 account to connect to AzureAD/Office365 and import the user data.

Paths to the Import, Export and Password scripts. Note: the Export and Password PS1 scripts files exist but are empty.

Object Type as configured in the Schema.ps1 file.

Attributes as configured in the Schema.ps1 file.

Anchor as per the Schema.ps1 file.

The rest of the MA configuration is up to your implementation. What you are going to join on and what attributes flow into the MV will vary based on your needs and solution. At a minimum you’d probably be looking to do a join on immutableID (after some manipulation) or UPN and flow in attributes such as AADAccountEnabled etc.

Completing the Configuration

To finalise the MA you’ll need to do the usual tasks of creating run profiles, staging the connector space from AzureAD/Office365 and syncing into the Metaverse. Once you’ve done your initial Stage/Full Sync you can perform Delta Sync’s.


A “Full Import” on a small AzureAD (~8500 Users) took 2 minutes.
A subsequent “Delta Import” with no changes took 6 seconds.

A similar implementation of the logic, but for Groups gives similar results/performance.
A  “Full Import” on a small AzureAD (~9800 Groups) took 5 minutes.
A subsequent “Delta Import” with 7 Adds (new Groups) and 157 Updates took 1 minute.


Follow Darren on Twitter @darrenjrobinson

Getting Users, Groups & Contacts via the Azure Graph API using Differential Query & PowerShell

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.

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.

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.

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.

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.


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

Goodbye Set-MsolUser, Hello Set-AzureADUser & Azure Graph API

Recently Microsoft released the preview of the v2.0 Azure AD PowerShell cmdlets.

I’ve got a project coming up where I’m looking to change my approach for managing users in Azure using Microsoft Identity Manager. Good timing to do a quick proof of concept to manage users with the new cmdlets and directly using the Graph API in preparation to move away from the msol cmdlets.

New Modules

First up, the Azure AD v2.0 PowerShell module was released in public preview on July 13, 2016. There will likely be changes before they become GA, so keep that in mind.

The v2.0 Azure AD PowerShell Module modules themselves are available for download from here

If you have Windows Management Framework v5 installed you can download and install from PowerShell (as below).

Once installed, pretty quickly you can import the module, authenticate to your tenant, retrieve a user and update a few attributes (as below).

Whilst functional it doesn’t really work for how we need to interact with Azure from an Identity Management perspective. So how can we still use PowerShell but enumerate and manipulate identities in Azure ?

Now that we have the AzureAD v2.0 module installed we can reference the Active Directory library it installs (Microsoft.IdentityModel.Clients.ActiveDirectory.dll), authenticate to our Tenant retrieve users, and update them. That’s exactly what is shown in the commands below.

Where interacting with the GraphAPI directly really shines however is at the directory services layer and the Differential Query functionality.

As such this is the approach that I’ll be taking for integration of Azure with Microsoft Identity Manager for managing users for entitlements (such as Azure licensing).
I hope this though also saves a few people time in working out how to use PowerShell to manage Azure objects via the Graph API (using both the PowerShell Module or via the RestAPI).

Implementing Application with Office 365 Graph API in App-only Mode

Microsoft has recently release Microsoft Graph to easily integrate Office 365 resources with applications. Graph API basically provides one single endpoint to call bunch of Web APIs to get access Office 365 resources.

In order to use Graph API from another application, the application must be registered in Azure Active Directory (AAD) first. When the application is registered, we can choose how the application is permitted to use resources – application permissions or delegate permissions. The latter one typically requires users to provide user credentials like username and password to get a proper access token. However, there must be requirements that the application doesn’t require users credentials but should directly access to Office 365 resources, which is called app-only mode. For example, a back-end Web API application doesn’t require user credentials to communicate with Graph API. There are many articles on the Internet dealing with user credentials but not many articles coping with this app-only mode. In this post, I will walk through how to register an application as app-only mode and consume Graph API through the registered application.

The sample code used here can be found here. This sample application is built-in ASP.NET 5 and ASP.NET MVC 6. Therefore, in order to get the best development experience, I would recommend using Visual Studio 2015.

Registering Application

OK. First thing goes first. As the sample application is using AAD and Graph API, it’s a mandatory to register this app on your AAD first. Please follow the steps below.

Create User Account on AAD

You can skip this step, if you have already got a user account on AAD.
NOTE: Microsoft Account won’t work with this sample app.

Create a user account on AAD tenant. Once created, the user account should be a co-administrator of the Azure subscription that is currently being used.

Register Application to AAD

  • Create a new application.

  • Choose the "Add an application my organization is developing" option.

  • Enter the application name like "Graph API App-only Sample" and select the "Web Application and/or Web API" option.

  • Enter "https://(tenant-name)/GraphApiAppOnlySample" for both fields. (tenant-name) should look like Please note that both won’t be used at all.

Now the app has been registered.

Configure Application

  • Once the app is registered, click the configure tab.

  • Get the Client ID.

  • Get the secret key. Note that the key is only displayed once after click the Save button at the bottom.

  • Add another application called Microsoft Graph

  • Give "Read directory data" permission to Microsoft Graph, as only this permission is necessary to run the sample app.

ATTENTION: In the production environment, appropriate number of application permissions MUST be given to avoid any security breach.

The app has been configured.

Update Settings in Sample Application

As the app has been registered and configured, the sample Web API app should be setup with appropriate settings. Firstly, open appsettings.json

Then change values:

  • Tenant: to your tenant name.
  • ClientId: Client ID from the app.
  • ClientSecret: Secret key from the app.
  • AppId: to your tenant name.

Trust IIS or IIS Express with a Self-signed Certificate

  • You can skip this step, if you intend to publish this app to Azure.
  • You can skip this step, if you already have a self-signed certificate on your root certificate storage.

All communications with AAD and Graph API are performed through a secure channel (SSL/TLS), this sample app MUST be signed with a root certificate. However, this is a developer’s local environment, so a self-signed certificate should be issued and stored as a root certificate. If you don’t store the self-signed certificate, you’ll see the following message popped up when you run VS2015.

The following steps show how to register self-signed certificate to the root certificate store using PowerShell.

Check Self-signed Certificate

First, Check if you have a self-signed certificate in your personal certificate store.

If there’s no certificate with name of CN=localhost, you should create the one using makecert.exe. The easiest way to execute makecert.exe is to run Developer Command Prompt for VS2015.

  • -r: Create a self signed certificate.
  • -pe: Mark generated private key as exportable.
  • -n: Certificate subject X509 name. eg) -n "CN=localhost"
  • -b: Start of the validity period in mm/dd/yyyy format; default to now.
  • -e: End of validity period in mm/dd/yyyy format; defaults to 2039.
  • -ss: Subject’s certificate store name that stores the output certificate. eg) -ss My
  • -len: Generated Key Length (Bits). Default to 2048 for ‘RSA’ and 512 for ‘DSS’.

Store Self-signed Certificate to Root Store

Second, store the self-signed certificate to the root store.

Finally, you can verify the self-signed certificate has been stored into the root store.

Build and Run Sample Web API Application

All setup has been completed! Now, build the solution in Visual Studio 2015 and punch F5 key to get into the Debug mode. Then you’ll get a JSON response of your tenant organisation details. How does it work? Let’s look into the code.

Get Access Token from AAD Using ADAL

In order to get an access token from AAD, we need to setup AuthenticationContext instance and call a method to get one. The code snippet below is an extract from the sample application.

The graphApp instance is created from appsettings.json and injected to the controller. With this instance, both AuthenticationContext instance and ClientCredential instance have been created. Note that the ClientCredential instance only uses clientId and clientSecret, not user credentials. In other words, this sample application won’t require any user to login and provide their login details. Let’s see the actual Get() method.

This is the part to get access token. The AuthenticationContext instance sends a request for Graph API with the ClientCredential instance only containing clientId and clientSecret. When the authentication fails, the Get() action will return the exception details as a JSON format. The authResult instance now contains access token.

Call Graph API with Access Token

Now, we have the access token. In the same action method, let’s see how it is consumed to call Graph API.

The access token is set to the request header. In this sample code, we call organization details through Graph API. If you use Fiddler, send a request to the application and you will see the full response details.

So far, we have had a brief look how to implement a simple Web API application as app-only mode to consume Graph API. As stated above, this sample application is not for production use unless proper permissions are given. Once all appropriate permissions are setup, you can easily customise this app for your integration purpose. Hope this will help your development.