从 Microsoft Teams (管理员) 的用户视图中删除外部聊天

作为租户管理员,可以使用新的 RemoveAllAccessForUser 图形 API从用户视图中删除外部启动的聊天。

Microsoft Teams 管理员可能需要删除组织外部人员创建的用户聊天。 例如,你的一个用户收到了来自公司外部某人的聊天请求。 该聊天可能包含不适当的或恶意内容,作为管理员,你可以删除该聊天以帮助保护你的用户。

若要使用 RemoveAllAccessForUser 图形 API,需要提供三个参数:tenantIduserIdchatsId/threadIdtenantId 是 Teams 租户的唯一标识符。 userId 是要删除其聊天的用户的唯一标识符。 chatsId/threadId 是要从中删除用户的 Teams 聊天线程的唯一标识符。

可以从新的统一审核日志 (UAL 获取这三个参数,) 外部用户与租户中的用户通信时生成的事件。 UAL 事件包含有关发件人、收件人、聊天线程和邮件的信息。 可以使用 UAL 事件来标识要从中撤消访问权限的聊天线程,然后从事件详细信息中提取 tenantIduserIdchatsId/threadId

使用 RemoveAllAccessForUser 图形 API

  • 步骤 1:搜索符合条件的 UAL 事件 。 如果要查找将用户添加到聊天的所有事件,可以在搜索查询中使用“MemberAdded”事件。
  • 步骤 2:从 UAL 事件详细信息中提取 tenantIduserIdchatsId/threadId
  • 步骤 3:使用所需参数调用 RemoveAllAccessForUser 图形 API

步骤 1:搜索 UAL 事件

若要搜索特定的 UAL 事件,可以使用 Search-UnifiedAuditLog 图形 API,也可以使用Microsoft Purview 合规门户中的审核日志搜索功能。 以下说明使用 Microsoft Purview 合规门户。 执行以下步骤:

  1. 以审核日志管理员身份登录 https://compliance.microsoft.com

  2. 在左侧导航中,选择“ 审核”。

  3. 在“审核日志搜索”页上,指定以下条件:

    • 在“审核”页上,选择“搜索”。
    • 活动:从“ 活动 - 操作名称 ”字段中选择“MemberAdded (”和“MessageReceived) ”,然后选择“ MicrosoftTeams ”作为 工作负载
    • 日期范围:选择涵盖外部用户与租户中用户通信的时间段的日期范围。 (可选的) 用户:输入租户中你感兴趣的用户的 UPN。
  4. 选择“搜索”。 此命令会将搜索排队,以在后台运行。

完成后,查看搜索结果并确定涉及你感兴趣的聊天和用户的 UAL 事件 (下面的步骤 3) 。

步骤 2:从 UAL 事件详细信息中提取 tenantId、userId 和 chatsId/threadId

若要从 UAL 事件详细信息中提取 tenantIduserIdchatsId/threadId ,可以使用事件的 OrganizationIdUserKeyChatThreadId 字段。 如果搜索了 MemberAdded 事件,则可能会看到用户已添加到外部聊天的事件,以及用户将外部用户添加到聊天的事件。 在 “成员 详细信息”部分查找租户中用户所在的事件, (指示这是已添加的用户,请参阅下面的图 2) 。 为此,请按照下列步骤操作:

  1. 选择涉及要撤消访问权限的外部用户的 UAL 事件之一。

  2. 在“事件详细信息”窗格中:

    • 复制 OrganizationId 字段的值。 此值是 Teams 租户的 tenantId
    • 复制 UserKey 字段的值。 此值是租户中已添加到聊天的用户的 userId
    • 复制 ChatThreatId 字段的值。 此值是消息所属的 Teams 聊天线程的 chatsId/threadId

请参阅以下屏幕截图,其中显示了 Purview 搜索结果详细信息的示例:

Microsoft Purview 搜索详细信息
图 1 (UAL MemberAdded 事件) 的详细信息

Microsoft Purview 成员详细信息
图 2 (MemberAdded UAL 事件) 的成员详细信息

步骤 3:使用所需参数调用 RemoveAllAccessForUser 图形 API

若要使用参数调用 RemoveAllAccessForUser 图形 API,需要使用对图形 API 的 HTTP POST 请求:

POST https://graph.microsoft.com/beta/chats/{chatsId}/removeAllAccessForUser 

{chatsId} 替换为要执行操作的聊天的 ID 。 请求正文应包含以下属性的 JSON 用户 对象:

  • tenantId:Teams 租户的 tenantID。
  • ID:租户中要从中移动聊天的用户的 userID。

例如,请求可能如下所示:

POST https://graph.microsoft.com/beta/chats/19:7d8980.........f94061cf8c2@unq.gbl.spaces/removeAllAccessForUser 
Content-Type: application/json 

{ 
  "user": { 
    "id" : "d864e79f-……..-0eeb4d61fdc2", 
    "tenantId": "2a690434-………-13600199a" 
  } 
} 

若要对请求进行身份验证,需要在 Authorization 标头中提供有效的访问令牌。 访问令牌应具有 Chat.ReadWrite.All 权限。 若要获取访问令牌,可以使用 Azure AD OAuth 2.0 终结点。 有关详细信息,请参阅 Microsoft Graph - 代表用户获取访问权限

如果请求成功,则响应的状态代码为“204 无内容”,正文为空。 如果请求失败,响应将包含错误代码和说明失败原因的消息。

可通过多种方式调用Microsoft 图形 API - 如果不熟悉该过程,请从图形资源管理器等交互式工具开始。 某些管理员创建应用或使用 PowerShell 与 Graph API 交互。

示例代码

以下 PowerShell 代码可用作起点。 此代码演示如何获取用户令牌、创建具有必要权限的客户端应用,以及如何使用该客户端应用调用图形 API以删除消息。

param(
    # Tenant id for the user whom the chat access is going to be removed
    [Parameter(Mandatory=$true)]
    [String]
    $TenantId,
 
    # User id for the user whom the chat access is going to be removed
    [Parameter(Mandatory=$true)]
    [String]
    $UserId,
 
    # Id of the chat that from which access will be removed
    [Parameter(Mandatory=$true)]
    [String]
    $ThreadId
)
 
 
# These may not all be necessary in your environment
# Install Microsoft.Graph.Authentication module for all users (requires admin rights)
if (Get-Module -ListAvailable -Name Microsoft.Graph.Authentication) {
    Write-Host "Microsoft.Graph.Authentication module found." -ForegroundColor "Green"
} 
else {
    Write-Host "Microsoft.Graph.Authentication module not found. Installing"
    Install-Module Microsoft.Graph.Authentication -Scope AllUsers -Force 
}
 
# Install Microsoft.Graph.Applications module for all users (requires admin rights)
if (Get-Module -ListAvailable -Name Microsoft.Graph.Applications) {
    Write-Host "Microsoft.Graph.Applications module found." -ForegroundColor "Green"
} 
else {
    Write-Host "Microsoft.Graph.Application module not found. Installing"
    Install-Module Microsoft.Graph.Applications -Scope AllUsers -Force 
}
 
# Install MSAL.PS module for all users (requires admin rights)
if (Get-Module -ListAvailable -Name MSAL.PS) {
    Write-Host "MSAL module found."  -ForegroundColor "Green"
} 
else {
    Write-Host "MSAL module not found. Installing"
    Install-Module MSAL.PS -Scope AllUsers -Force 
}
 
 
# Connect to graph and verify that a client application exists for this purpose - if not, create one
Connect-MgGraph -Scopes "Application.ReadWrite.All", "DelegatedPermissionGrant.ReadWrite.All"
 
# Get client app info
$App = Get-MgApplication -Filter "DisplayName eq 'RemoveAllAccessForUserApp'"
$createAppParams = @{
    publicClient = @{
		redirectUris = "https://login.microsoftonline.com/common/oauth2/nativeclient"
	}
}
 
# If client app is not found. Create it
if ($null -eq $App)
{
    Write-Host "Client app not found. Creating new one." -ForegroundColor "Yellow"
    $App = New-MgApplication -DisplayName 'RemoveAllAccessForUserApp' @createAppParams
    Write-Host "Client app created. Waiting for 5 seconds before continuing." -ForegroundColor "Yellow"
    Start-Sleep -Seconds 5
}
else 
{
    $AppId = $App.AppId
    Write-Host "Client app with id '$AppId' found'" -ForegroundColor "Green"
}

$ClientId = $App.AppId
 
# Now that we have the ID for our client application, we can call the RemoveAccessForUser API...
# Msal parameters required to get access token.
$MsalParams = @{
    ClientId = $ClientId
    TenantId = $TenantId
    Scopes   = 'Chat.ReadWrite.All'
}
 
 
# Get access token, it will prompt for interactive login   
$MsalResponse = Get-MsalToken @MsalParams
$AccessToken  = $MsalResponse.AccessToken
 
 
# Request authorization header containing the access token
$AuthHeader = @{
    Authorization = "Bearer $AccessToken"
}
 
# Request url
$apiUrl = "https://graph.microsoft.com/beta/chats/$ThreadId/removeAllAccessForUser"
 
# Prepare request body
$Body = @{
	user = @{
		id = "$UserId"
		tenantId = "$TenantId"
	}
}
 
$Body = $Body | ConvertTo-Json
 
# Execute request
Write-Host "Executing RemoveAllAccessForUser request."
 
try {
    Invoke-RestMethod  -Headers $AuthHeader -Uri $apiUrl -Method POST -ContentType 'application/json' -Body $Body 
    Write-Host "Rquest to RemoveAllAccessForUser api succeeded." -ForegroundColor "Green"
} catch {
    Write-Host "Request to RemoveAllAccessForUser api failed." -ForegroundColor "Red"
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
    $receiveStream = $_.Exception.Response.GetResponseStream();
    Write-Host ([System.Text.Encoding]::ASCII).GetString($receiveStream.ToArray())
}
 
Write-Host "Disconnecting from Microsoft Graph!"
Disconnect-MgGraph