How to Monitor New Members Added to Teams

Monitor New Teams Members and Remove Undesired Members Automatically

A question in the Office 365 Technical Discussions Facebook group asked about a script to monitor member additions to Teams. If the new member comes from specific departments, they should be removed. The script should then post details of new members that pass the check to a team channel.

On the surface, this seems to be an ideal situation for Information Barriers, a Microsoft Purview solution designed to keep designated groups of users from communicating with each other. However, Information Barriers require Office 365 E5 or above and it’s a solution that’s best suited when hard barriers must be enforced.

Sketching Out a Solution to Monitor New Teams Members

A custom solution isn’t too difficult to design. The essential steps are:

  • Periodically search the unified audit log to find events captured when a new member joins a group. The example script searches for events occurring within the last three hours.
  • Check if the group is one of the monitored set (defined in an array of group identifiers). If it is, record details of the group and the user. Clearly, you could use whatever criteria you wanted to check new team members.
  • For some reason, searching the unified audit log can return multiple instances of add member events. This might be part of the problems the audit log has suffered recently. To remove duplicates, the script sorts the list of detected events.
  • Loop through the deduplicated events and check the department for each added member. If the department is on the banned list, remove the user from the group. If not, post a message to a designated channel in the team to announce their arrival.

Teams also posts notices about new users to the information pane (Figure 1). The advantage of doing it this way is the ability to remove members plus do whatever other processing is desired.

Notification of new members in the information pane
Figure 1: Notification of new members in the information pane

Posting Teams Channel Messages

As covered in this article, several methods exist to post messages to Teams channels. Briefly:

  • The Submit-PnpTeamsChannelMessage cmdlet. A connection to PnP must be established first and the signed in account must be a member of the target team.
  • The New-MgTeamChannelMessage from the Microsoft Graph PowerShell SDK. This cmdlet only supports delegate permissions (Channel.Send.Message), meaning that the signed-in account must be a member of the target team.
  • Connect the Incoming Webhook connector to the target channel and post a JSON-format message to the connector. This method works without authentication.

To illustrate the principles behind the solution, I choose to use the SDK method because the script already used the Get-MgUser cmdlet to fetch details of user departments.

Diving Into the Code to Monitor New Teams Members

Here’s the code used to search for audit records and extract information from records of interest:

$StartDate = (Get-Date).AddHours(-3)
$EndDate = (Get-Date).AddHours(1)

Write-Host "Searching for audit records..."
[array]$Records = Search-UnifiedAuditLog -Start $StartDate -End $EndDate -Operations "Add member to group" -Formatted -ResultSize 500
If (!($Records)) { Write-Host "No member additions to groups to check" ; break }

Write-Host "Processing audit records..."
$MembersReport = [System.Collections.Generic.List[Object]]::new() 
ForEach ($Rec in $Records) {
  $AuditData = $Rec.AuditData | ConvertFrom-Json
  $GroupId = $AuditData.ModifiedProperties | Where-Object {$_.Name -eq 'Group.ObjectID'} | Select-Object -ExpandProperty NewValue
  $GroupName = $AuditData.ModifiedProperties | Where-Object {$_.Name -eq 'Group.DisplayName'} | Select-Object -ExpandProperty NewValue
  $UserAdded = $AuditData.ObjectId
  $Actor = $Rec.UserIds
  If ($GroupId -in $GroupsToCheck) {
    $UserData = Get-MgUser -UserId $UserAdded -Property Id, displayName, department
    $ReportLine = [PSCustomObject]@{
      Team       = $GroupName
      User       = $UserAdded
      UserName   = $UserData.displayName
      UserId     = $UserData.Id
      Addedby    = $Actor
      Timestamp  = $Rec.CreationDate
      Department = $UserData.Department
      GroupId    = $GroupId
      Id         = ("{0}_{1}_{2}" -f $GroupName, $UserAdded, $Rec.CreationDate) }
    $MembersReport.Add($Reportline)
  }
}

And here’s how the script processes member removals and posting notifications for approved new members:

ForEach ($R in $MembersReport) {
  If ($R.Department -in $ExcludedDepartments) {
     Write-Host ("User {0} with department {1} will be removed from team" -f $R.User, $R.Department) -ForegroundColor Red
     Remove-MgGroupMemberByRef -DirectoryObjectId $R.UserId -GroupId $R.GroupId 
  } Else {
    Write-Host ("Sending channel message about new team member {0}" -f $R.UserName) -ForegroundColor Yellow
    [string]$UserName = $R.UserName
    $HtmlContent = "<h1>New User Has Joined Our Team</h1>
               <h2>$UserName has joined this team</h2><p></p>
               <p>Please welcome <b>$UserName</b> to the team. They will bring great joy to all of us!</p>"
    $Message = (New-MgTeamChannelMessage -TeamId $TargetTeamId -ChannelId $TargetTeamChannelId -Body @{Content = $HTMLContent; ContentType = "html"} -Subject "New User Join Report" -Importance "High")
  }
}

Figure 2 shows an example of the message posted to Teams. The content of the message is very simple HTML and could easily be enhanced to communicate whatever sentiments are desired.

New member notification posted to a Teams channel

Monitor new teams members
Figure 2: New member notification posted to a Teams channel

Improve the Solution to Monitor New Teams Members

I don’t pretend that this script is a complete solution. It would be more effective to run as a scheduled Azure Automation runbook (here’s an example of a runbook that monitors audit events). At a pinch, it could run as a scheduled task on a workstation, but I prefer Azure Automation to Windows Scheduler for several reasons. In any case, the principle is proven and now it’s up to you to take the code forward and make it work the way you want. You can download the sample script from GitHub.


Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.