Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more โ all from one place.
๐ Launch ToolkitIn Microsoft Teams, some groups have HiddenMembership visibility enabled โ meaning their member lists are concealed for confidentiality or security reasons. These teams are often used for sensitive projects or executive collaboration. Keeping track of them helps administrators maintain oversight, ensure compliance, and prevent accidental misconfiguration.
This Graph PowerShell script retrieves all Teams in your tenant with HiddenMembership visibility, generates a detailed CSV report, and automatically emails it to administrators.
Import-Module Microsoft.Graph -ErrorAction Stop
Connect-MgGraph -Scopes "Group.Read.All","Team.ReadBasic.All","Mail.Send"
$FromUser = "admin@contoso.com"
$ToList = "it-ops@contoso.com;teams-admin@contoso.com"
$Subject = "HiddenMembership Teams Report"
$CsvOutDir = "$env:TEMP"
$teamsGroups = Get-MgGroup -All -Property Id,DisplayName,Visibility,CreatedDateTime,ResourceProvisioningOptions `
-Filter "resourceProvisioningOptions/Any(x:x eq 'Team')"
$hiddenTeams = @()
foreach ($g in $teamsGroups) {
if ($g.Visibility -ne "HiddenMembership") { continue }
$ownerObjs = Get-MgGroupOwner -GroupId $g.Id -All -ErrorAction SilentlyContinue
$ownerNames = @()
$ownerMails = @()
foreach ($o in ($ownerObjs | Where-Object { $_ })) {
$name = $o.AdditionalProperties['displayName']
$mail = $o.AdditionalProperties['mail']
if ($name) { $ownerNames += $name }
if ($mail) { $ownerMails += $mail }
}
$hiddenTeams += [PSCustomObject]@{
TeamId = $g.Id
DisplayName = $g.DisplayName
Visibility = $g.Visibility
CreatedDate = $g.CreatedDateTime
Owners = ($ownerNames -join "; ")
OwnerEmails = ($ownerMails -join "; ")
}
}
if (-not (Test-Path -Path $CsvOutDir)) { New-Item -ItemType Directory -Path $CsvOutDir | Out-Null }
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = Join-Path $CsvOutDir ("HiddenMembership_Teams_{0}.csv" -f $ts)
$hiddenTeams | Sort-Object DisplayName | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $csvPath
$total = $hiddenTeams.Count
$summaryHtml = @"
<html>
<body style='font-family:Segoe UI,Arial,sans-serif'>
<h3>HiddenMembership Teams Report</h3>
<p>Total HiddenMembership teams: <b>$total</b></p>
<p>Attached CSV includes: TeamId, DisplayName, Visibility, CreatedDate, Owners, OwnerEmails.</p>
</body>
</html>
"@
$fileBytes = [System.IO.File]::ReadAllBytes($csvPath)
$base64Content = [System.Convert]::ToBase64String($fileBytes)
$attachment = @{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = [System.IO.Path]::GetFileName($csvPath)
contentBytes = $base64Content
contentType = "text/csv"
}
$recipients = @()
$ToList.Split(@(';', ','), [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
$addr = $_.Trim()
if ($addr) { $recipients += @{ emailAddress = @{ address = $addr } } }
}
$mail = @{
message = @{
subject = "$Subject"
body = @{ contentType = "HTML"; content = $summaryHtml }
toRecipients = $recipients
attachments = @($attachment)
}
saveToSentItems = $true
}
Send-MgUserMail -UserId $FromUser -BodyParameter $mail
Write-Host "Done. CSV saved at: $csvPath" -ForegroundColor Green
The script connects using Connect-MgGraph with the scopes Group.Read.All, Team.ReadBasic.All, and Mail.Send for Teams and mail access.
It fetches all Microsoft 365 groups that are provisioned as Teams using the resourceProvisioningOptions property.
The script isolates only those Teams where the Visibility is set to HiddenMembership.
For each matching team, it retrieves owner names and email addresses using Get-MgGroupOwner.
The script compiles the list into a CSV report and sends it as an email attachment to administrators, along with an HTML summary.
| Error | Cause | Solution |
|---|---|---|
| Access Denied | Insufficient Graph permissions | Use the correct scopes: Group.Read.All, Team.ReadBasic.All, Mail.Send. |
| Empty CSV | No hidden Teams found | Confirm whether your tenant contains any Teams with HiddenMembership. |
| Send-MgUserMail fails | Sender mailbox missing | Ensure $FromUser has a valid Exchange mailbox. |
| Request_UnsupportedQuery | Incorrect filter syntax | Verify the Graph filter syntax exactly matches resourceProvisioningOptions/Any(x:x eq 'Team'). |
| Owners missing | Team owners not assigned | Verify team ownership in Microsoft Teams admin center. |
This Graph PowerShell script gives administrators clear visibility into Teams configured with HiddenMembership, often used for confidential collaboration. By automating this report and delivering it via email, IT admins can maintain proper oversight of hidden Teams, ensuring compliance and visibility into sensitive collaboration spaces across Microsoft 365.
© m365corner.com. All Rights Reserved. Design by HTML Codex