Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions scripts/Add-EngageGroupAdmins/Add-EngageGroupAdmins.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<#
.DESCRIPTION
The sample scripts are not supported under any Microsoft standard support
program or service. The sample scripts are provided AS IS without warranty
of any kind. Microsoft further disclaims all implied warranties including,
without limitation, any implied warranties of merchantability or of fitness for
a particular purpose. The entire risk arising out of the use or performance of
the sample scripts and documentation remains with you. In no event shall
Microsoft, its authors, or anyone else involved in the creation, production, or
delivery of the scripts be liable for any damages whatsoever (including,
without limitation, damages for loss of business profits, business interruption,
loss of business information, or other pecuniary loss) arising out of the use
of or inability to use the sample scripts or documentation, even if Microsoft
has been advised of the possibility of such damages.

Purpose:
-Bulk-adds admins (owners) to Viva Engage communities using the Microsoft Graph API.
A Viva Engage community admin is simply an owner of the community's underlying
Microsoft 365 group, so this uses the group owners API:
https://learn.microsoft.com/en-us/graph/api/group-post-owners
https://learn.microsoft.com/en-us/graph/api/resources/engagement-api-overview#community-membership-management

Author:
Dean Cron

Version:
1.0 - Initial Release 2023 (legacy Yammer REST API)
2.0 - Updated to v2 October 2025 (legacy Yammer REST API)
3.0 - July 2026 - Migrated off the deprecated Yammer REST API to the Microsoft Graph
group-owners API. NOTE: the GroupID column now needs the Microsoft 365 group ID
(a GUID) that backs the community, NOT the legacy numeric Yammer group ID used
by earlier versions of this script. See the README for how to get this ID.

Requirements:

1. An Azure AD (Entra ID) App Registration with the following Microsoft Graph
**application** permission, with admin consent granted:
-Group.ReadWrite.All

2. CSV containing group IDs and admins to add to each. See the README for more information
on how to create this and how to find the group ID for a community:
https://github.com/microsoft/FastTrack/tree/master/scripts/Add-EngageGroupAdmins/README.md


.EXAMPLE
.\Add-EngageGroupAdmins.ps1
#>

<############ STUFF YOU NEED TO MODIFY ############>

#Point this to the groupadmins.csv you created as per the requirements.
$groupadminsCsvPath = 'C:\temp\groupadmins.csv'

# Change these to match your environment. Instructions:
# https://learn.microsoft.com/en-us/graph/auth-v2-service?view=graph-rest-1.0
$ClientId = "clientid"
$TenantId = "tenantid"
$ClientSecret = "clientsecret"

<############ YOU SHOULD NOT HAVE TO MODIFY ANYTHING BELOW THIS LINE ############>

#Make sure groupadmins.csv is where it's supposed to be
try {
$groupadminsCsv = Import-Csv $groupadminsCsvPath
}
catch {
Write-Host "Unable to open the input CSV file. Ensure it's located at $groupadminsCsvPath"
Return
}

function Connect-ToGraph {
param (
[Parameter(Mandatory = $true)]
[string]$ClientId,

[Parameter(Mandatory = $true)]
[string]$TenantId,

[Parameter(Mandatory = $true)]
[string]$ClientSecret
)

$authBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
Client_Id = $ClientId
Client_Secret = $ClientSecret
}

$Connection = Invoke-RestMethod -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token -Method POST -Body $authBody
return $Connection.access_token
}

$accessToken = Connect-ToGraph -ClientId $ClientId -TenantId $TenantId -ClientSecret $ClientSecret
$authHeader = @{ Authorization = "Bearer $accessToken"; 'Content-Type' = 'application/json' }

Write-Host "Starting to add group admins..." -ForegroundColor Cyan

$groupadminsCsv | ForEach-Object {
do {
$rateLimitHit = $false

$gID = $_.GroupID
$mail = $_.Email

try {
#Add the user as an owner of the group. Group owners are automatically treated as
#admins of the associated Viva Engage community.
$requestBody = @{ '@odata.id' = "https://graph.microsoft.com/v1.0/users/$mail" } | ConvertTo-Json
Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/groups/$gID/owners/`$ref" -Headers $authHeader -Method POST -Body $requestBody | Out-Null

Write-Host "Successfully added admin $mail to group $gID" -ForegroundColor Green
}
catch {
$statusCode = $_.Exception.Response.StatusCode.Value__
if ($statusCode -eq "429" -or $statusCode -eq "503") {
#Deal with rate limiting
#https://learn.microsoft.com/en-us/graph/throttling
$rateLimitHit = $true
}
elseif ($statusCode -eq "401" -or $statusCode -eq "403") {
#Thrown when the access token is invalid or lacks Group.ReadWrite.All
Write-Host "Exiting script, Graph API reports ACCESS DENIED. Ensure the app registration has Group.ReadWrite.All (application) permission with admin consent." -ForegroundColor Red
exit
}
elseif ($statusCode -eq "404") {
#Typically thrown when either the group or user isn't found.
Write-Host "Exiting script, Graph API reports 404, typically caused when either the user ($mail) or group ($gID) was not found" -ForegroundColor Red
exit
}
elseif ($statusCode -eq "400") {
#Typically thrown when the user is already an owner of the group
Write-Host "Failed to add" $mail "to group" $gID "- Graph API reports 400, the user may already be an owner" -ForegroundColor Red
}
else {
$l = $_.InvocationInfo.ScriptLineNumber
Write-Host "Failed to add" $mail "to group" $gID -ForegroundColor Red
Write-Host "error $statusCode on line $l"
}
}
if ($rateLimitHit) {
#429 or 503: Sleep for a bit before retrying
Write-Host "Rate limit hit, sleeping for 15 seconds"
Start-Sleep -Seconds 15
}
} while ($rateLimitHit)
}

Write-Host "All done!" -ForegroundColor Cyan
Original file line number Diff line number Diff line change
@@ -1,50 +1,47 @@
# Microsoft FastTrack Open Source - Add-YammerGroupAdmins
# Microsoft FastTrack Open Source - Add-EngageGroupAdmins

This sample script will allow a Yammer admin to bulk-add group owners to groups in their network.
This sample script will allow an admin to bulk-add admins (owners) to Viva Engage communities using the Microsoft Graph API.

**Version 3.0 note:** This script was migrated off the deprecated legacy Yammer REST API to the Microsoft Graph [group owners API](https://learn.microsoft.com/en-us/graph/api/group-post-owners), since the legacy endpoint is undocumented, unsupported, and at risk of being turned off without notice. A Viva Engage community admin is simply an owner of the community's underlying Microsoft 365 group, so this uses `/groups/{groupId}/owners/$ref` rather than a community-specific endpoint. **The ID format has changed as part of this migration** — see below.

## Usage

### Prerequisites

- You must create a new Yammer app registration in Microsoft Entra ID. This app should be configured to grant the following **delegated** permission:
- You must create a new app registration in Microsoft Entra ID. This app should be configured to grant the following **application** permission, with admin consent granted:
```
Yammer
-access_as_user
Microsoft Graph
-Group.ReadWrite.All
```

- You'll need to create a CSV file containing two columns:
- **GroupID**. This will contain the IDs of the groups you want to add a new admin to.
- **Email**. This will contain the email address of the user you want to assign as admin of the group represented by the GroupID value next to it.

The CSV should look similar to this:
- **GroupID**. This will contain the Microsoft 365 group ID (a GUID) backing the community you want to add a new admin to.
- **Email**. This will contain the email address (UPN) of the user you want to assign as admin of the community represented by the GroupID value next to it.

![CSV format](groupadminssample.jpg?raw=true "Title")
> ⚠️ **This is not the same ID as the legacy numeric Yammer group ID used by earlier versions of this script.** Graph requires the underlying Microsoft 365 group's GUID.

You can get the group ID of the groups you need to add the admins to in one of two ways:
You can get the Microsoft 365 group ID for a community in one of two ways:

1. Grab the group ID from the group's URL and use a BASE64 decoder on the string at the end as described here: https://support.microsoft.com/en-us/office/how-do-i-find-a-community-s-group-feed-id-in-yammer-9372ab6f-bcc2-4283-bb6a-abf42dec970f
2. Run a network data export going back as far as possible (do not export attachments) and get the group ID from the groups.csv file generated: https://learn.microsoft.com/en-us/rest/api/yammer/network-data-export
1. `GET https://graph.microsoft.com/beta/employeeExperience/communities/{communityId}` — the response includes a `groupId` field with the Microsoft 365 group ID.
2. `GET https://graph.microsoft.com/beta/employeeExperience/communities` and match communities by `displayName` to find the corresponding `groupId`.

There are 4 variables you need to change in the script itself. These are located very early in the script just below “<############ STUFF YOU NEED TO MODIFY ############>”:

1. **$ClientId = "ClientIDString"**
1. **$groupadminsCsvPath = 'C:\temp\groupadmins.csv'**

Point this to the groupadmins.csv file you created as mentioned above.

2. **$ClientId = "ClientIDString"**

>Replace ClientIDString with the Client ID of the app registration you created in the prerequisites.

2. **$TenantId = "TenantIDString"**
3. **$TenantId = "TenantIDString"**

>Replace TenantIDString with the Client ID of the app registration you created in the prerequisites.
>Replace TenantIDString with the Tenant ID of the app registration you created in the prerequisites.

3. **$ClientSecret = "ClientSecretString"**
4. **$ClientSecret = "ClientSecretString"**

>Replace ClientSecretString with the client secret value of the app registration you created in the prerequisites.

4. **$RedirectUri = "https://localhost"**
>Replace this with the redirect Url you set in your app registration (if not set to https://localhost)

4. **$groupadminsCsvPath = 'C:\temp\groupadmins.csv'**

Point this to the groupadmins.csv file you created as mentioned above.

### Parameters

Expand All @@ -54,24 +51,23 @@ None

Once you’ve completed the pre-reqs, you’re ready to go. Run the script like so:

.\Add-YammerGroupAdmins.ps1
.\Add-EngageGroupAdmins.ps1

### Notes

**If you encounter the following error: 'Get-MsalToken : Error creating window handle.', set your PowerShell window's default terminal application to 'Windows Console Host'. This is due to a [known bug in MSAL](https://github.com/AzureAD/MSAL.PS/issues/58)**

**This sample calls an undocumented endpoint in the Yammer REST APIs, and as such has no official support provided for it, and may stop working without warning.**
**This sample now uses the Microsoft Graph group-owners API (`/v1.0/groups/{groupId}/owners/$ref`), which is officially documented and supported, unlike the earlier version of this script.**

## Applies To

- Yammer / Viva Engage networks in M365
- Viva Engage communities in M365

## Author

|Author|Original Publish Date
|----|--------------------------
|Dean Cron, Microsoft|June 23th, 2023|
-> Updated to v2|October 2nd, 2025
-> Updated to v3, migrated to Microsoft Graph|July 22nd, 2026

## Issues

Expand Down
Loading
Loading