Tag Archives: Azure AD Nested Groups

Recursively enumerate Azure AD Group members with PowerShell

Many of the scripts used to assign licenses for Azure AD / Office 365 users are utilizing groups to assign the licenses. On the topic I have received quite a lot requests on nested group support, which is not possible with Get-MsolGroupMember as of now.

To solve this problem, I have built a simple function canned Get-JDMSOLGroupMember. It checks if a group consists of other groups, and loops through them until all group members of all groups have been enumerated. In the end it will sort the members so that no duplicate member records are returned. It will only return users, not groups.

See the screenshot below on how it works:


function Get-JDMsolGroupMember { 
    The function enumerates Azure AD Group members with the support for nested groups.
    Get-JDMsolGroupMember 6d34ab03-301c-4f3a-8436-98f873ec121a
    Get-JDMsolGroupMember -ObjectId  6d34ab03-301c-4f3a-8436-98f873ec121a -Recursive
    Get-MsolGroup -SearchString "Office 365 E5" | Get-JDMsolGroupMember -Recursive
    Author   : Johan Dahlbom, johan[at]dahlbom.eu
    Blog     : 365lab.net 

        [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)]
        [ValidateScript({Get-MsolGroup -ObjectId $_})]
    begin {
        $MSOLAccountSku = Get-MsolAccountSku -ErrorAction Ignore -WarningAction Ignore
        if (-not($MSOLAccountSku)) {
            throw "Not connected to Azure AD, run Connect-MsolService"
    process {
        Write-Verbose -Message "Enumerating group members in group $ObjectId"
        $UserMembers = Get-MsolGroupMember -GroupObjectId $ObjectId -MemberObjectTypes User -All
        if ($PSBoundParameters['Recursive']) {
            $GroupsMembers = Get-MsolGroupMember -GroupObjectId $ObjectId -MemberObjectTypes Group -All
            if ($GroupsMembers) {
                Write-Verbose -Message "$ObjectId have $($GroupsMembers.count) group(s) as members, enumerating..."
                $GroupsMembers | ForEach-Object -Process {
                    Write-Verbose "Enumerating nested group $($_.Displayname) ($($_.ObjectId))"
                    $UserMembers += Get-JDMsolGroupMember -Recursive -ObjectId $_.ObjectId 
        Write-Output ($UserMembers | Sort-Object -Property EmailAddress -Unique) 
    end {

As usual, let me know if you find issues or have any other suggestions.