Using PowerShell to Check Group or Team Membership

PowerShellRescue

Probing Membership for Office 365 Groups, Teams, and Azure AD Groups

When I wrote “A Teams PowerShell Primer,” about a year ago, I spent some happy days hacking my way through the Teams PowerShell module, weak and flawed as it is. Although the module has improved since (and is now at 0.9.6), some problems still remain. For example, we have the Get-TeamUser and Add-TeamUser cmdlets to report team membership and add a new team member, all of which is nice. What the module does not include is any way to detect whether a user is a member of a group (team).

The same challenge exists for the cmdlets available for Office 365 Groups, which are part of the Exchange Online module. Again, we have cmdlets to add someone to a group (Add-UnifiedGroupLinks) and return group membership (Get-UnifiedGroupLinks), but nothing to tell us if an account is already a member. The cmdlets for Teams and Office 365 Groups both work against Azure AD Groups, so it comes as no surprise that the native cmdlets offer no relief either.

The question therefore is “given a user account, what’s the best way to check whether the user is a member of a group (or team)?”

The Classic Approach

There are many joys to be found in PowerShell. One of these is that many examples and suggestions exist about how to attack problems. If you browse the web, most of the solutions involve iterating down through the group membership to find if a specific member is present. Iteration is fine if the membership is small, but as Office 365 Groups and Teams both support up to 2,500 members, performance suffers as membership grows.

Another way of checking is to populate an array with the object identifiers for the group membership against which you want to check. We can then use the object identifier for the user object to look for a match. Something like this does the job:

$Check = (Read-Host "Enter User Principal Name to check")
$User = (Get-AzureADUser -ObjectId $Check)
$Obj = $User.ObjectId
$GroupId = "6c3405c6-9556-4c04-8c36-ca46eb6a44d8"
$GroupMembers = (Get-AzureADGroupMember -ObjectId $GroupId | Select ObjectId)
If ($GroupMembers -Match $Obj) {
    Write-Host $User.DisplayName "is part of" (Get-AzureAdGroup -ObjectId $GroupId).DisplayName}

Office 365 Groups are more Complex

Our code works nicely when we have a User Principal Name (UPN) to find the object identifier for an Azure Active Directory account. However, the people who run the code might not know the UPN of the user. In addition, the membership of Office 365 Groups (including the ones used for Teams) can include guests. A guest member also has an Azure Active Directory account (the UserType property for these accounts is “Guest”), but the UPNs and other properties differ from accounts belonging to users in the tenant.

Using a Hash Table of Email Addresses

One way to address the problem is to check against a property that every member will have – their email address. As noted above, groups can now have large memberships, so a hash table is a good choice to hold the information to check against.

In this code extract, we populate a hash table with details of members. Each entry in the hash table has a name and value and will look like this:

Name                           Value
----                           -----
Kim Akers                      [email protected]
Paul Cunningham                [email protected]

To populate the hash table, we process local users differently to guest users to extract the same information for both.

$GroupMembers = @{}
$OrgName = “@”+ (Get-OrganizationConfig).Identity
$CheckGroup = (Read-Host "Enter name of group to check")
$TargetGroup = (Get-UnifiedGroup -Identity $CheckGroup)
# Populate the array with current group membership
Get-UnifiedGroupLinks -LinkType Member -Identity $TargetGroup.Alias | % {
   $User = $_.Name.tostring()
   # Handle guest users
   if ($User -like "*#EXT#*") {
      $GuestUPN = $User+$OrgName
      $GuestUser = Get-AzureADUser -ObjectId $GuestUPN -ErrorAction SilentlyContinue
      $GroupMembers.Add($GuestUser.DisplayName, $GuestUser.Mail) }
   else {
      # local mailbox
      $LocalUser = $Email = (Get-Mailbox -Identity $User)
      $GroupMembers.Add($LocalUser.DisplayName, $LocalUser.PrimarySmtpAddress) }
}

Now we have a table of user names and email addresses, we can check someone against the group membership:

$Check = (Read-Host "Enter name of user to check")
If ($GroupMembers.ContainsKey($Check) -eq $False) { 
        Write-Host $Check "is not in" $TargetGroup.DisplayName }
    Else {
        Write-Host $Check "is a member of" $TargetGroup.DisplayName }

The check is very fast even if the hash table is very large, which means that this is a good approach to use to check whether someone is a group member. The hash table also holds the email address for each member, so it is easy to extend the check to accommodate lookups against display names or email addresses.

Adding Distribution List Members to a Team

Because every Microsoft Team has an Office 365 Group and share a common membership, the code also works for Teams. However, Teams has its own directory, and if you want to manipulate team membership instead of just checking it, you should use the cmdlets in the Teams PowerShell module to ensure that any change you make is immediately picked up by Teams.

In this example, we want to add the local mailboxes in the membership of an Exchange distribution list to a team. Again, we use a hash table to store the current team membership to avoid adding a member who is already present. This code asks for the target team and uses the Get-TeamUser cmdlet to read its membership to populate the hash table.

PromptTeam = (Read-Host “Enter Target Team”)
$TargetTeamId = (Get-UnifiedGroup -Identity $PromptTeam).ExternalDirectoryObjectId
If ($TargetTeamId -ne $Null) {
  $SourceDL = "GDPR Working Group"
  #Create hash table to look up existing team members
  $TeamMembers = @{}
  Get-TeamUser -GroupId $TargetTeamId | % {
   $User = $_.User.tostring()
   # Handle guest users
   if ($User -like "*#EXT#*") {
      $GuestUser = Get-AzureADUser -ObjectId $User
      $TeamMembers.Add($GuestUser.DisplayName, $GuestUser.Mail) }
   else {
      # local mailbox
      $Email = $_.User
      $User = $_.Name
      $TeamMembers.Add($User, $Email) }
  }

Now we can read the membership of the source distribution list and add new members to the team.

$DLUsers = Get-DistributionGroupMember -Identity $SourceDL
   ForEach ($U in $DLUsers) {
          $CheckUserEmail = (Get-Mailbox -Identity $U.Name).PrimarySmtpAddress 
          If ( $TeamMembers.ContainsValue($CheckUserEmail) -eq $False) {
             {Add-TeamUser -GroupId $TargetTeamId -User $CheckUserEmail -Role Member } 
   }
}

More to Find About Group Membership

Of course, figuring out whether a user is a member of a group or team is only one of the things you can do with PowerShell and there are many other variations on the theme to consider. Vasil Michev has an excellent post on the topic about using the Get-Recipient and Get-AzureADUser cmdlets to interrogate membership data.

I am sure that some of the more experienced PowerShell gurus have better techniques to check users against group membership. But I enjoyed the few hours I spent playing around with scripts to explore using hash tables. Hopefully, you find the information useful too!

Follow Tony on Twitter @12Knocksinna.

Want to know more about how to manage Office 365? Find what you need to know in “Office 365 for IT Pros”, the most comprehensive eBook covering all aspects of Office 365. Available in PDF and EPUB formats (suitable for iBooks) or for Amazon Kindle.