Getting All Office 365 Groups and Group Owners with PowerShell

Sometime you might need to get list of all your Office 365 Groups from your tenant and list Group Owners for every group.

You can do this with PowerShell and Microsoft Graph API.

There is List Groups and List Owners interfaces in Microsoft Graph API. By combining these two interfaces, we can create script for listing the groups and their owners. Finally we can export the results to CSV-file for later use.

Using Microsoft Graph API in PowerShell

If you are already familiar with PowerShell, you might know that you can use Invoke-RestMethod command in PowerShell.

Before you can call Microsoft Graph API in your Office 365 tenant, you have to set application permission to call API. If you are not familiar about the Graph API authentication and permissions, see more information from Graph API Authentication overview provided by Microsoft. 

There is also instructions in a GitHub how to connect the the Microsoft Graph using Application Permissions.

Once you have set Application Permissions, you can start using Microsoft Graph API in PowerShell.

Get all Office 365 Groups

You can get all office 365 group by using the List Groups API.
I have filtered the Office 365 groups by using filter parameter $filter=groupTypes/any(g:g eq ‘Unified’)”

$uriGroups = "https://graph.microsoft.com/v1.0/groups?`$filter=groupTypes/any(g:g eq 'Unified')"

Then you can call Graph API by using Invoke-RestMethod in Powershell.

I have made while loop for the pagination because the Graph API will return max. 1000 groups in List Groups response.

$GroupsResponse = (Invoke-RestMethod -Uri $uriGroups –Headers $Header –Method "Get" -ContentType "application/json")
    $Groups = $GroupsResponse.value

    $GroupsNextLink = $GroupsResponse."@odata.nextLink"

        while ($GroupsNextLink -ne $null){
            $GroupsResponse = (Invoke-RestMethod -Uri $GroupsNextLink –Headers $Header –Method "Get" -ContentType "application/json")
            $GroupsNextLink = $GroupsResponse."@odata.nextLink"
            $Groups += $GroupsResponse.value
        }

You can sort the results by using the properties, when you have get your response from the Graph API. I have used Group Display name and Group ID.

$Groups | Sort-Object -Property displayName | Select-Object -Property displayName, id | ForEach-Object {
    write-Host "------" 
    write-Host "Display Name:" $_.displayName
    write-Host "ID:" $_.id
    $GroupTitle = $_.displayName

Get group owners for specific group

Then we need to get the group owners for the group. I have passed the group ID to the $uriOwners variable. So the Graph Api Rest Call for Group Owners will look like this.

$uriOwners = "https://graph.microsoft.com/v1.0/groups/{" + $_.id  +"}/owners

We can get Group owners using the List Owners API. I have sorted the results by user Display Name and added to the group owners to the string queue using the variable $GroupOwners += $_.displayName + “; “

  #Get group onwers
    $GroupOwners = ""
    $uriOwners = "https://graph.microsoft.com/v1.0/groups/{" + $_.id  +"}/owners"
    $OwnersResponse = (Invoke-RestMethod -Uri $uriOwners –Headers $Header –Method "Get" -ContentType "application/json")
    $OwnersResponse.value | Sort-Object -Property displayName | Select-Object -Property displayName | ForEach-Object {
        write-Host "Owner Display Name:" $_.displayName
        $GroupOwners += $_.displayName + "; "
    }

Set values for CSV-export

Then we can set the results from the groups and group owners to the ordered list for CSV-export.

   #Set values for csv export
    $details = [ordered] @{
    GroupTitle = $GroupTitle.ToString(); 
    GroupID = $_.id.ToString();
    GroupOwners = $GroupOwners.ToString();                      
    }    
    $resultsCsv += New-Object PSObject -Property $details

Finally save the results and export the CSV-file

We call export-CSV for exporting results to the script root Reports-folder. I have also used Start-Transcript command for record all part of PowerShell session to the a text file.

write-host "Operation completed successfully" -ForegroundColor Green
write-host "Founded groups:" $Groups.value.Count.ToString() -ForegroundColor Green
#Export results to CSV-file
$resultsCsv | export-Csv -Path "$PSScriptRoot\Reports\Office365GroupsWithOwners$TransciptStartTime.csv" -NoTypeInformation -Delimiter ";" -Encoding Unicode
Stop-Transcript

As a results you will have CSV-file where you have your Office 365 Groups and their Onwers in a three columns:

  • GroupTitle
  • GroupID
  • GroupOwners

Whole script

Script will write the founded groups and their owners in PowerShell session and save the transcript file and csv-file to the script roots Reports-folder. Note! you have to create Reports-folder manually.

Here is the whole script.

#Get all Office 365 groups from tenant and list group owners

$TransciptStartTime = (Get-Date -UFormat %Y%m%d-%H%M).ToString();
Start-Transcript -Path "$PSScriptRoot\Reports\Office365GroupsWithOwners$TransciptStartTime.txt"

$resultsCsv = @()

write-host "Getting all Office 365 groups from tenant via Graph API" -ForegroundColor Green

#Create header
$Header =  @{Authorization = "Bearer $accessToken"}
$uriGroups = "https://graph.microsoft.com/v1.0/groups?`$filter=groupTypes/any(g:g eq 'Unified')"

write-host $uri

$GroupsResponse = (Invoke-RestMethod -Uri $uriGroups –Headers $Header –Method "Get" -ContentType "application/json")
    $Groups = $GroupsResponse.value

    $GroupsNextLink = $GroupsResponse."@odata.nextLink"

        while ($GroupsNextLink -ne $null){
            $GroupsResponse = (Invoke-RestMethod -Uri $GroupsNextLink –Headers $Header –Method "Get" -ContentType "application/json")
            $GroupsNextLink = $GroupsResponse."@odata.nextLink"
            $Groups += $GroupsResponse.value
        }

write-host "Founded groups:" $Groups.value.Count.ToString() -ForegroundColor Green

$Groups | Sort-Object -Property displayName | Select-Object -Property displayName, id | ForEach-Object {
    write-Host "------" 
    write-Host "Display Name:" $_.displayName
    write-Host "ID:" $_.id
    $GroupTitle = $_.displayName

    #Get group onwers
    $GroupOwners = ""
    $uriOwners = "https://graph.microsoft.com/v1.0/groups/{" + $_.id  +"}/owners"
    $OwnersResponse = (Invoke-RestMethod -Uri $uriOwners –Headers $Header –Method "Get" -ContentType "application/json")
    $OwnersResponse.value | Sort-Object -Property displayName | Select-Object -Property displayName | ForEach-Object {
        write-Host "Owner Display Name:" $_.displayName
        $GroupOwners += $_.displayName + "; "
    }
   
    #Set values for csv export
    $details = [ordered] @{
    GroupTitle = $GroupTitle.ToString(); 
    GroupID = $_.id.ToString();
    GroupOwners = $GroupOwners.ToString();                      
    }    
    $resultsCsv += New-Object PSObject -Property $details
            
} 

write-host "Operation completed successfully" -ForegroundColor Green
write-host "Founded groups:" $Groups.value.Count.ToString() -ForegroundColor Green
#Export results to CSV-file
$resultsCsv | export-Csv -Path "$PSScriptRoot\Reports\Office365GroupsWithOwners$TransciptStartTime.csv" -NoTypeInformation -Delimiter ";" -Encoding Unicode
Stop-Transcript

2 thoughts on “Getting All Office 365 Groups and Group Owners with PowerShell

    1. Hi User101, You can add Property called “Visibility” to your code. For example:
      $Groups | Sort-Object -Property displayName | Select-Object -Property displayName, id, visibility | ForEach-Object {
      write-Host “——”
      write-Host “Display Name:” $_.displayName
      write-Host “ID:” $_.id
      write-Host “GroupVisibilty:” $_.visibility
      $GroupTitle = $_.displayName

      By that way you have group visibility (Public or Private) in your group objects.

      Then remember add that visibility also to csv file export.

      #Set values for csv export
      $details = [ordered] @{
      GroupTitle = $GroupTitle.ToString();
      GroupID = $_.id.ToString();
      GroupVisibilty = $_.visibility.ToString();
      GroupOwners = $GroupOwners.ToString();
      }
      $resultsCsv += New-Object PSObject -Property $details

      And then you can filter groups by visibility in your csv-file using Excel.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s