Graph API: Using the Microsoft Graph ASPNet Library in PowerShell for O365 Group Management

O365 groups are called Unified Groups. They can be managed

From an Admin or End user view from the Azure commandlets or the Exchange commandlets.

From a developer perspective via

  1. Azure Graph api : This is on the road to deprecation and Microsoft does not advice to use this. New features are not being added.
  2. Microsoft Graph api: This is the Microsoft recommended api to be used, it has a lot of features and is updated regularly.

The Microsoft Graph api is a REST api and there are two ways to use the api

  1. Use the REST api commands directly. There is a developer reference. You can access this via C# or PowerShell.
  2. Use the Graph ASP SDK library which presents a friendlier interface with the api commands run at the backend. It could sometimes be limited. There is a C# code on Github for this. This blog post is a conversion of that code to PowerShell so you can access it in PowerShell as well.

Items to Note about the Graph api

  1. Permissions should be as granular as possible. You can use O365 roles but Microsoft has also provided more granular permissions that can be given to the application.
  2. Sometimes a time delay is operations due to the Azure shared environment. Allow few seconds between operations.
  3. An Azure AD subscription should be connected to your O365 subscription.
  4. Paging should done when making import query to Azure. It can be a client initiated paging where you set the number of items per page that should be returned or it could a server initiated paging where Azure only returns a limited number of items because it is busy. My recommendation is to develop for server initiated paging, with each query will be the request to the server to tell you if it still has more results to send. Most times you will get all your results in one query.
  5. You need to get an access token and then use that token to do your operations.

Pre-Requirements

Get the following dlls from the C# package. Store them somewhere on your PC

  • Microsoft.IdentityModel.Clients.ActiveDirectory.dll
  • Microsoft.Graph.Core.dll
  • Microsoft.Graph.dll
  • Newtonsoft.Json.dll

Code


$path = "C:\coding\assemblies"
[System.Reflection.Assembly]::LoadFrom("${env:ProgramFiles(x86)}\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\System.Net.Http.dll") | Out-Null
[System.Reflection.Assembly]::LoadFrom("$path\Microsoft.IdentityModel.Clients.ActiveDirectory.dll") | Out-Null
[System.Reflection.Assembly]::LoadFrom("$path\Microsoft.Graph.dll") | Out-Null
$Assem =@(
"${env:ProgramFiles(x86)}\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6\System.Net.Http.dll",
"$path\Microsoft.IdentityModel.Clients.ActiveDirectory.dll",
"$path\Microsoft.Graph.Core.dll",
"$path\Microsoft.Graph.dll",
"$path\Newtonsoft.Json.dll"
)
$Source = @"
using Microsoft.Graph;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Configuration;
using System.Net.Http;
using System.Threading.Tasks;

namespace MicrosoftGraphWrapper
{
public class AzureAuthenticationProvider : IAuthenticationProvider
{
public Task AuthenticateRequestAsync(HttpRequestMessage request)
{
Task t = new Task(() =>
{
string clientId = “355de491-7856-4f81-8ceb-ca6b317a976c”;
string clientSecret = “R77lWd/ytjhFKSqJbD555rtyyLBSXeXw2GZfmJYFdaqRw=”;
string authority = “https://login.microsoftonline.com/mydomain.onmicrosoft.com”;
AuthenticationContext authContext = new AuthenticationContext(authority);
ClientCredential creds = new ClientCredential(clientId, clientSecret);
string accessToken = authContext.AcquireTokenAsync(“https://graph.microsoft.com”, creds).Result.AccessToken;
Request.Headers.Add(“Authorization”, “Bearer ” + accessToken);
});
t.Start();
return t;
}
}
}
“@
Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp
Function GetGroups()
{
“ID DisplayName”
$allGroups = $null;
$authProvider = New-Object MicrosoftGraphWrapper.AzureAuthenticationProvider
$graphClient = New-Object Microsoft.Graph.GraphServiceClient -ArgumentList $authProvider
$groups = $graphClient.Groups.Request().OrderBy(“displayName”).GetAsync().Result;
$allGroups = $groups;
while ($groups.NextPageRequest -ne $null)
{
$groups = $groups.NextPageRequest.GetAsync().Result;
foreach ($gp in $groups)
{
$allGroups.Add($gp);
}
}
foreach ($gp in $allGroups)
{
$gp.Id + ” ” + $gp.DisplayName
}
“—End—”
}
Function AddMemberToGroup($groupID, $memberID)
{
Try
{
$authProvider = New-Object MicrosoftGraphWrapper.AzureAuthenticationProvider
$graphClient = New-Object Microsoft.Graph.GraphServiceClient -ArgumentList $authProvider

$member = New-Object Microsoft.Graph.DirectoryObject;
$member.Id = $memberID;
$graphClient.Groups[$groupID].Members.References.Request().AddAsync($member);

Write-Host “Member added”
}
Catch
{
Write-Host “Unable to add member”
}
}
Function RemoveMemberFromGroup($groupID, $memberID)
{
Try
{
$authProvider = New-Object MicrosoftGraphWrapper.AzureAuthenticationProvider
$graphClient = New-Object Microsoft.Graph.GraphServiceClient -ArgumentList $authProvider
$member = New-Object Microsoft.Graph.DirectoryObject;
$member.Id = $memberID;
$graphClient.Groups[$groupID].Members[$memberID].Reference.Request().DeleteAsync();
Write-Host “Member removed”
}
Catch
{
Write-Host “Unable to remove member”
}
}
Function CreateGroup($groupName)
{
$authProvider = New-Object MicrosoftGraphWrapper.AzureAuthenticationProvider
$graphClient = New-Object Microsoft.Graph.GraphServiceClient -ArgumentList $authProvider
$types = New-Object System.Collections.Generic.List[string];
$types.Add(“Unified”);
$group = New-Object Microsoft.Graph.Group;
$group.DisplayName = $groupName;
$group.Description = $groupName;
$group.GroupTypes = $types;
$group.MailEnabled = $true;
$group.MailNickname = $groupName.Replace(” “, “”);
$group.SecurityEnabled = $false;

$gp = New-Object Microsoft.Graph.Group;
$gp = $graphClient.Groups.Request().AddAsync($group).Result;
$gp
}