Thursday, February 25, 2021

Synchronize membership from an AD group to a Microsoft 365 group

A client recently wanted to control access to Microsoft Stream content by using members of an AD security group that is already synchronized into Azure AD. However, Microsoft Stream access can only be controlled by using Microsoft 365 groups (formerly Office 365 groups). This led to identifying how we can synchronize the group membership from the AD group to the Microsoft 365 group.

The first option I thought of was Windows PowerShell. This is certainly possible, but it would need to be run as a scheduled task with credentials stored securely. Have reliance on an on-premises scheduled task was suboptimal. So, I went searching and found a template name Synchronize an Azure AD Group with an Office 365 Group on a recurring basis in Power Automate (formerly Flow) that is for exactly this purpose.


At a high level, this is what the flow does:

  • Sets a schedule for running
  • Queries membership from a source group
  • Queries membership from a target group
  • Compares the source and target group membership
  • Adds source members members not present in the target group
  • Sends a notification email identifying source members that were added
  • Identifies target members that are not present in the source group (with the option to provide and exceptions list of target members not to remove)
  • Sends an approval request to remove target members that are not present in the source group
  • Removes target members that are not present in the source group when the request is approved

When you add the template it will prompt you for permissions to create connections required to run the flow. The Office 365 Groups and Azure AD connectors require credentials to query and modify group memberships.

After you've created the flow from the template there are a few items that you need to configure in the flow. The Recurrence box defines how often the flow runs. The example below is configured to run the flow daily at 2am.

Next you need to configure the SourceGroupID and the TargetGroupID. You need to obtain the Object Id attribute for these groups from either the Azure AD admin center or Windows PowerShell. The Object ID for the group is placed in the Value box. There are separate steps for SourceGroupID and TargetGroupID. Effectively, these are populating variables used later in the script.

You also need to define the ApprovedOwnerUPN. This user approves removals from the target group when necessary. Enter the UPN for that user into the Value box.

Members in the target group that are not members in the source group are removed. If there are some unique members that you want to remain in the target group, you can define them in the ExcludedFromRemove variable. This might be useful for cloud only users such as an admin account.

To define the user accounts that are not removed, click on the createArray function in the Value box. This opens a box where you can manually enter the users you don't want to remove. In the screenshot below, and are excluded from removal.

The List source group members and List target group members steps allow you to define a maximum number of results that are returned. By default, this value is 500. You need to define this value large enough to gather the entire membership of each group. Enter the number of group members in the Top box. If you leave this value blank, only 100 results are returned.

If your groups have membership higher than 1000 then you need to perform additional configuration to allow more than 1000 results. Click the ellipsis in the List source group members step and then select Settings to get the following screen. To allow more than 1000 results you need to turn on pagination and specify the number of results you want to allow. The example below allows up to 2000 members. After you've done this, the Top value is ignored.

The only other issue I had when using this flow was related to the officeLocation attribute of the user objects in Azure AD. This attribute correlates with the physicalDeliveryOfficeName attribute in on-premises AD and is visible as Office on the General tab of a user in Active Directory Users and Computers.

If the officeLocation attribute is blank, then the flow fails. In the environments I deal with, this value is often blank. Rather than putting in dummy office information, we can edit the flow to ignore the null value. 

The two affected steps are:

  • Parse UsersAdded values in Send mail if UsersAdded variable is not empty
  • Parse MembersToRemove values in Get approval if UsersToRemove is not empty

Both of these steps have a Schema box that defines how attributes are selected from earlier data. The officeLocation attribute is defined as a string and thus fails when there is a null value. A quick way to fix this problem is by removing officeLocation from the schema. Remove the three lines are highlighted from both steps.

An alternative that I haven't tested is modifying the acceptable values for officeLocation. You can see that above officeLocation, the mobilePhone attribute allows the type to be either string or null. I believe that syntax would also work for officeLocation.

For more information about Power Automate (formerly Flow), see:


  1. Hey, thanks for this, saved me a massive headache!!

    For info, I only changed the officelication field to accepted string and null using your example above, and that sorted it!!


  2. This is very helpful. I'm having trouble though with a warning that says:
    Power Automate Approvals has not been installed for this environment. Run this approval flow to initiate provisioning.

    Any help would be appreciated

  3. Hi. Thanks so much for this! Do you know how I can remove the approver options so that it just removes and adds automatically without approval?

    1. I don't have the detailed steps, but it's definitely possible. You'd need to go into the Get approval if UsersToRemove is not empty step. In there you can remove the logic that does the approval and just do the update instead.

    2. Hi Byron. Thanks for your quick response! That really helped. I have used this tutorial for a lot of flows now but unfortunately I have run into an error where they stop working due to a error "Group id should be a valid guid - unable to parse [group id here...]". Removing and readding the group ID does not fix the error and I have posted in the PowerAutomate forum but no luck yet.... google also returns not much help so I am turning to you, hopefully you will know something about this?! Thanks!

    3. Off the top of my head, if the GUID for the group is correct, maybe it's related to the type of group. Sometimes, security groups, distribution groups, mail-enabled security groups, and M365 groups are treated differently. In particular, M365 (unified) groups seem to have their own set of rules.