Managing group memberships through the Microsoft Entra ID portal comes with a frustrating limitation: you are forced to check users individually. When auditing or reporting requires a complete list of every user and their assigned groups, the web interface simply cannot handle the request. This article will show you how to bypass this restriction and leverage PowerShell to easily extract and export all Microsoft Entra ID group memberships in bulk.
Install Microsoft Graph PowerShell
Before you start, you must Install the Microsoft Graph PowerShell module. Start Windows PowerShell as administrator and run the command below.
Install-Module Microsoft.Graph -ForceCode language: CSS (css)Important: Always update to the latest Microsoft Graph PowerShell module version before you run a cmdlet or script to prevent errors and incorrect results.
Connect to Microsoft Graph PowerShell
Connect-MgGraph -Scopes "Directory.Read.All", "Sites.Read.All"Code language: CSS (css)Download Export-GroupMemberships PowerShell script
To download the Export-GroupMemberships.ps1 PowerShell script, follow these steps:
- Create the folders temp and scripts in the (C:) drive if you don’t have them already
- Download the Export-GroupMemberships.ps1 PowerShell script
- Or copy the script below into Notepad and save it as Export-GroupMemberships.ps1 file
# Define parameters for the script
param (
[Parameter(Mandatory = $true, HelpMessage = "Enter the User ID (e.g., email or object ID) of the Entra ID user", ParameterSetName = "SingleUser")]
[string]$UserId,
[Parameter(Mandatory = $false, HelpMessage = "Specify the path for the CSV output file")]
[string]$CsvFilePath,
[Parameter(Mandatory = $false, HelpMessage = "Enable to display results in Out-GridView")]
[switch]$OutGridView,
[Parameter(Mandatory = $false, HelpMessage = "Process all users in the tenant", ParameterSetName = "AllUsers")]
[switch]$All
)
# Connect to Microsoft Graph with the required scopes
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All" -NoWelcome
# Initialize a List[Object] to store group details
$Report = [System.Collections.Generic.List[Object]]::new()
try {
# Determine whether to process a single user or all users
$UsersToProcess = if ($All) {
Write-Host "Fetching all users from the tenant..." -ForegroundColor Cyan
Get-MgUser -All -ErrorAction Stop
}
else {
Write-Host "Fetching user: $UserId" -ForegroundColor Cyan
Get-MgUser -UserId $UserId -ErrorAction Stop | Select-Object -First 1
}
# Check if any users were found
if (-not $UsersToProcess) {
Write-Host "No users found." -ForegroundColor Cyan
return
}
# Iterate through each user
foreach ($User in $UsersToProcess) {
Write-Host "Processing group memberships for user: $($User.UserPrincipalName)" -ForegroundColor Cyan
# Fetch the groups the user is a member of
$EntraGroupMembers = Get-MgUserMemberOf -UserId $User.Id -All -ErrorAction SilentlyContinue
# Check if the user is a member of any groups
if (-not $EntraGroupMembers) {
Write-Host "No group memberships found for user: $($User.UserPrincipalName)" -ForegroundColor Yellow
# Add a record for users with no group memberships
$GroupDetails = [PSCustomObject]@{
UserId = $User.Id
UserPrincipalName = $User.UserPrincipalName
DisplayName = $User.DisplayName
GroupId = "N/A"
GroupDisplayName = "N/A"
GroupEmail = "N/A"
SecurityEnabled = "N/A"
MailEnabled = "N/A"
GroupType = "N/A"
Source = "N/A"
}
# Add the group details to the report list
$Report.Add($GroupDetails)
continue
}
# Iterate through each group membership
foreach ($EntraGroup in $EntraGroupMembers) {
# Extract group details from AdditionalProperties
$AdditionalProperties = $EntraGroup.AdditionalProperties
# Determine group type based on groupTypes, securityEnabled, and mailEnabled
$GroupType = if ($AdditionalProperties.groupTypes -contains "Unified" -and $AdditionalProperties.securityEnabled) {
"Microsoft 365 (security-enabled)"
}
elseif ($AdditionalProperties.groupTypes -contains "Unified" -and -not $AdditionalProperties.securityEnabled) {
"Microsoft 365"
}
elseif (-not ($AdditionalProperties.groupTypes -contains "Unified") -and $AdditionalProperties.securityEnabled -and $AdditionalProperties.mailEnabled) {
"Mail-enabled security"
}
elseif (-not ($AdditionalProperties.groupTypes -contains "Unified") -and $AdditionalProperties.securityEnabled) {
"Security"
}
elseif (-not ($AdditionalProperties.groupTypes -contains "Unified") -and $AdditionalProperties.mailEnabled) {
"Distribution"
}
else {
"N/A"
}
# Create a custom object for the group details, including user information
$GroupDetails = [PSCustomObject]@{
UserId = $User.Id
UserPrincipalName = $User.UserPrincipalName
DisplayName = $User.DisplayName
GroupId = $EntraGroup.Id
GroupDisplayName = if ($AdditionalProperties.displayName) { $AdditionalProperties.displayName } else { "N/A" }
GroupEmail = if ($AdditionalProperties.mail) { $AdditionalProperties.mail } else { "N/A" }
SecurityEnabled = if ($AdditionalProperties.securityEnabled) { $AdditionalProperties.securityEnabled } else { "N/A" }
MailEnabled = if ($AdditionalProperties.mailEnabled) { $AdditionalProperties.mailEnabled } else { "N/A" }
GroupType = $GroupType
Source = if ($AdditionalProperties.onPremisesSyncEnabled) { "On-Premises" } else { "Cloud" }
}
# Add the group details to the report list
$Report.Add($GroupDetails)
}
}
# Output the results to the console (sorted by UserPrincipalName, then GroupDisplayName)
$Report | Sort-Object UserPrincipalName, GroupDisplayName | Format-Table -AutoSize
# Display results in Out-GridView if the switch is enabled
if ($OutGridView) {
$Report | Sort-Object UserPrincipalName, GroupDisplayName | Out-GridView -Title "Group Memberships Report"
}
# Export to CSV only if CsvFilePath is provided
if ($CsvFilePath) {
$Report | Sort-Object UserPrincipalName, GroupDisplayName | Export-Csv -Path $CsvFilePath -NoTypeInformation -Force
Write-Host "Group memberships exported to $CsvFilePath" -ForegroundColor Cyan
}
}
catch {
# Handle errors (e.g., invalid UserId, insufficient permissions, or Graph API issues)
Write-Host "An error occurred: $($_.Exception.Message)" -ForegroundColor Red
}Code language: PHP (php)4. Save the Export-GroupMemberships.ps1 PowerShell script in the C:\scripts folder

Export group memberships for single user
Export a list of group memberships for a single user with PowerShell.
C:\scripts.\Export-GroupMemberships.ps1 -UserId "<a href="mailto:[email protected]">[email protected]</a>"Code language: HTML, XML (xml)The PowerShell output shows these results.

Export a list of group memberships for a single user ([email protected]) to an Out-GridView.
C:\scripts\.\Export-GroupMemberships.ps1 -UserId "amanda.hansen@m365info.com" -OutGridViewCode language: CSS (css)
Export a list of group memberships for a single user ([email protected]) to a CSV file.
C:\scripts\.\Export-GroupMemberships.ps1 -UserId "amanda.hansen@m365info.com" -CsvFilePath "C:\temp\GroupMemberships.csv"Code language: CSS (css)
Run the PowerShell command below to export a list of group memberships for a single user ([email protected]) to an Out-GridView and CSV file.
C:\scripts\.\Export-GroupMemberships.ps1 -UserId "amanda.hansen@m365info.com" -OutGridView -CsvFilePath "C:\temp\GroupMemberships.csv"Code language: CSS (css)Export group memberships for all users
To export a list of group memberships for all users in Microsoft 365, specify the CSV path in the PowerShell command below.
C:\scripts\.\Export-GroupMemberships.ps1 -AllCode language: CSS (css)The PowerShell output shows these results.

Export a list of group memberships for all users to an Out-GridView.
C:\scripts\.\Export-GroupMemberships.ps1 -All -OutGridViewCode language: CSS (css)The Out-GridView appears.

Export a list of group memberships for all users to a CSV file.
C:\scripts\.\Export-GroupMemberships.ps1 -All -CsvFilePath "C:\temp\GroupMemberships.csv"Code language: CSS (css)Open the CSV file with an application like Microsoft Excel to see the results below.

Export a list of group memberships for all users to an Out-GridView and CSV file.
C:\scripts\.\Export-GroupMemberships.ps1 -All -OutGridView -CsvFilePath "C:\temp\GroupMemberships.csv"Code language: CSS (css)Read More: How To Install Microsoft Graph PowerShell Module
FAQ
Why can’t I export group memberships for all users at once directly from the Microsoft Entra ID portal?
The Microsoft Entra ID web interface is intentionally designed to display group memberships on a strict per-user basis for performance and data privacy reasons. Extracting a bulk report of all users and their respective groups inherently requires using Microsoft Graph PowerShell.
Which API permissions (Scopes) do I need to approve when connecting via Graph PowerShell?
To successfully read user objects and their associated group memberships, you must grant specific read permissions during your initial connection. You need to run Connect-MgGraph -Scopes "User.Read.All", "GroupMember.Read.All" to provide the necessary admin consent on the tenant.
Which specific PowerShell cmdlets drive this bulk export process in the background?
A standard export script relies on two primary cmdlets. First, it uses Get-MgUser to pull the complete list of users (fetching properties like UPN and DisplayName). Then, it processes each user through a loop using Get-MgUserMemberOf (or Get-MgGroup to resolve the objects) to gather their assigned memberships.
How is the data formatted in the CSV output for a user who belongs to dozens of groups?
Instead of creating a new row for every single group, the PowerShell script typically concatenates all group names into a single text string separated by semicolons (;) or commas (,). When you open the resulting CSV in Excel, each user occupies exactly one row, with all their memberships neatly compiled in a single “Groups” column.
Is it possible to filter the exported report to only show specific group types, such as Security Groups?
Yes, you can easily achieve this by adding a brief logical condition inside the script’s loop. By checking the GroupTypes or SecurityEnabled properties returned by the Get-MgUserMemberOf cmdlet, you can instruct the script to only write Security groups or Microsoft 365 groups to the final CSV file.






