【问题标题】:MicrosoftTeams cmdlets not working with AccessTokenMicrosoftTeams cmdlet 无法使用 AccessToken
【发布时间】:2021-04-29 03:49:40
【问题描述】:

我正在尝试在 C# Web 应用程序中从 powershell 模块 MicrosoftTeams(版本 2.0.0)运行 cmdlet。我正在使用本文提供的答案中的授权代码流和代码来获取令牌:Acquire AAD token using ASP.Net web forms。注意:我已将代码中的资源更改为 graph.windows.net 以获取 AAD 令牌。 Token是通过AuthenticationContext.AcquireTokenByAuthorizationCodeAsync方法获取的。

获取令牌后,我运行以下行以在 C# 中创建一个 powershell 实例并导入 MicrosoftTeams 模块。

PowerShell pshell
InitialSessionState iss;
iss = InitialSessionState.CreateDefault2();
iss.ImportPSModule(new[] { "MicrosoftTeams" });
pshell = PowerShell.Create(iss);

然后为了连接 MicrosoftTeams,我运行以下代码:

var connectCmd = new Command("Connect-MicrosoftTeams");
connectCmd.Parameters.Add("AadAccessToken", AccessToken);
connectCmd.Parameters.Add("AccountId", "xxxxxxx@xxxxxx.onmicrosoft.com");
pshell.Commands.AddCommand(connectCmd);
var result1 = pshell.Invoke();

代码到这里都可以正常工作。

之后,我清除 shell 命令并调用 Get-CsTeamsCallingPolicy cmdlet:

pshell.Commands.Clear();
pshell.Streams.Error.Clear();

pshell.AddScript("Get-CsTeamsCallingPolicy");
var result2 = pshell.Invoke();

Invoke 后出现异常,弹出如下对话框:

按“继续”会多次返回相同的对话。

此屏幕的异常详细信息是:

System.Collections.Generic.KeyNotFoundException was unhandled by user code
  HResult=-2146232969
  Message=The given key was not present in the dictionary.
  Source=mscorlib
  StackTrace:
       at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)
       at Microsoft.TeamsCmdlets.Powershell.Connect.Models.AzureSessionProvider.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\Models\AzureSession.cs:line 80
       at Microsoft.TeamsCmdlets.Powershell.Connect.TeamsPowerShellSession.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\TeamsPowerShellSession.cs:line 82
       at Microsoft.TeamsCmdlets.PowerShell.Connect.GetCsInternalAccessToken.ProcessRecord() in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\GetCsInternalAccessToken.cs:line 61
       at System.Management.Automation.CommandProcessor.ProcessRecord()

第三次按继续后,控制权返回到 C# 代码,我收到以下运行时异常:

Exception calling "GetSteppablePipeline" with "1" argument(s): 
"Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): 
"Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets."" 

尝试从 powershell 编辑器运行此逻辑会显示类似的行为:

运行以下两行:

$AccessToken =  'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 
Connect-MicrosoftTeams -AadAccessToken $AccessToken -AccountId 'xxxxxxx@xxxxxx.onmicrosoft.com'

给出这个结果:

Account                         Environment Tenant                               TenantId                            
-------                         ----------- ------                               --------                            
xxxxxxx@xxxxxx.onmicrosoft.com AzureCloud  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

然后我运行 Get-Team cmdlet:

Get-Team -User xxxxxxx@xxxxxxx.onmicrosoft.com

导致此消息:

Get-Team : The given key was not present in the dictionary.
At line:1 char:1
+ Get-Team -User xxxxxxx@xxxxxxx.onmicrosoft.com
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-Team], KeyNotFoundException
    + FullyQualifiedErrorId : System.Collections.Generic.KeyNotFoundException,Microsoft.TeamsCmdlets.PowerShell.Custom.GetTeam

运行 cmdlet Get-CsTeamsCallingPolicy 会产生此结果

Exception calling "GetSteppablePipeline" with "1" argument(s): 
"Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): 
"Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets.""
At C:\Program Files\WindowsPowerShell\Modules\MicrosoftTeams\2.0.0\net472\SfBORemotePowershellModule.psm1:11369 char:13
+             $steppablePipeline = $scriptCmd.GetSteppablePipeline($myI ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : CmdletInvocationException

如果我在不提供访问令牌和帐户 ID 的情况下直接运行 Connect-MicrosoftTeams,我会看到登录屏幕,登录后一切正常,但 AadAccessToken 不会发生。

如果在 web 应用程序和 powershell 编辑器中通过 Connect-AzureAD cmdlet 连接到 AzureAD 模块,相同的代码可以正常工作:

Connect-AzureAD -AadAccessToken $AccessToken -AccountId 'xxxxxxx@xxxxxxx.onmicrosoft.com'

如果有人遇到并成功解决了这个问题,或者有一些关于如何解决这个问题的提示,请帮助。

我已经尝试了很多东西,包括搜索特定的异常消息和任何可能的解决方案,但在这种特殊情况下没有找到任何帮助,安装了最新版本的 MSTeams 模块,以前的版本是旧的并且没有我希望使用的所有 cmdlet。我实际上还安装了 MSTeams 模块的预览版,以查看此问题是否在即将发布的版本中得到修复。卸载已弃用的 SkypeForBuisnessOnline 连接器模块、更新的窗口等。如果您查看Connect-MicrosoftTeams 的 Microsoft 文档中的示例 4,这就是我所关注的。

【问题讨论】:

  • 您使用哪个流程来获取令牌?客户凭证,委托等?据我所知,您目前只能将用户获取的令牌用于团队 cmdlet。也许在应用注册上添加 impersonate_user 权限可能会解决这个问题。
  • 我正在使用授权代码流,用户被重定向到 azure 广告登录页面。成功登录和 MFA 后,会返回访问令牌,可在应用程序中检索该令牌。我在哪里可以找到 azure 中的 impersonate_user 权限?我在 API 权限部分没有看到这样的权限。
  • 您是如何使用 AadAccessToken 连接到 Microsoft Teams 的?

标签: powershell oauth-2.0 azure-active-directory microsoft-teams microsoft-graph-teams


【解决方案1】:

你的实现有几个问题,下面我会一一解释。

answer in this post 生成 Microsoft Graph 访问令牌,而不是 AAD Graph 访问令牌。但是你把它写成-AadAccessToken。您应该在此处将其设为 -MsAccessToken,因为 Get-Team 正在调用 Microsoft Graph。但我们不能简单地使用Connect-MicrosoftTeams -MsAccessToken $AadAccessToken-AccountId 'xxxxxxx@xxxxxx.onmicrosoft.com',因为-AadAccessToken 是必需的。所以为了测试的目的,我们可以把它设置成-MsAccessToken

因此您可以使用此 cmd 连接到 Microsoft Teams:

Connect-MicrosoftTeams -AadAccessToken $AadAccessToken -MsAccessToken $AadAccessToken -AccountId 'xxxxxxx@xxxxxx.onmicrosoft.com'

那么你就可以成功运行Get-Team -User xxxxxxx@xxxxxxx.onmicrosoft.com了。

但是这里会有另一个问题。 Get-CsTeamsCallingPolicy 是 Skype For Business Powershell 模块下的 cmd。在运行 cmdlet 之前,我们必须运行 Connect-MicrosoftTeams(在 Teams 模块中)或 new-csonlinesession(在 SFB 模块中)。

表示Get-CsTeamsCallingPolicy调用 Microsoft Graph 或 AAD Graph。

所以使用-AadAccessToken-MsAccessToken 的连接方法不够让您从SFB 模块运行此命令。

我知道您不想在此处再次以交互方式执行登录以运行 Powershell cmd。但是,由于您的帐户已经启用了 MFA,静态登录将不再适用。

接下来我尝试按照示例 3 here 连接服务主体。

Connect-MicrosoftTeams -TenantId c3eac90d-eb4b-48ef-ac86-7acac472d3cd -CertificateThumbprint 9b6ac64bfb8b48dbb53cca75fb33ce2d -applicationid daaaf729-aaff-45ba-8055-a39dd618fe24

然后错误Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets.被绕过但是我在运行`Get-CsTeamsCallingPolicy时遇到了一个新错误:

Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): "Tenant Domain is empty"

但我在使用服务主体登录时明确指定了租户 ID。

所以我认为 Microsoft Teams 模块目前没有与 SFB 模块很好地集成。

您的设计无法以这种方式实现。

希望我的所有发现对您有所帮助。

【讨论】:

  • 我在代码中将资源更改为 graph.windows.net 但忘了提及。我对-MsAccessToken-AadAccessToken 使用相同的值进行了测试。然后运行 ​​Get-Team -User xx@xx.xyz.com 我收到错误:Access token validation failure. Invalid audience. SFBO 已弃用,Microsoft 要求使用 Teams 模块。在检查最新团队模块中可用的 cmdlet 时,我看到 Get-CsTeamsCallingPolicy 可用:(Get-Module -Name MicrosoftTeams).ExportedCommands。当我在没有任何参数的情况下运行Connect-MicrosoftTeams 时,Get-TeamsGet-CsTeamsCallingPolicy 工作正常。谢谢
  • @kshab 您应该获得 Microsoft Graph 令牌而不是 AAD Graph 令牌(这可以解决错误 Access token validation failure. Invalid audience.)。我在回答中提到过。而且我知道Get-TeamsGet-CsTeamsCallingPolicy 在没有任何参数的情况下运行Connect-MicrosoftTeams 时工作正常。这是因为它获得了一个用于调用 Get-Teams 的 Microsoft Graph 访问令牌和另一个用于调用 Get-CsTeamsCallingPolicy 的访问令牌(可能是用于 SFB)。
  • @kshab 但是当你使用Connect-MicrosoftTeams -AadAccessToken $AadAccessToken -MsAccessToken $AadAccessToken -AccountId 'xxxxxxx@xxxxxx.onmicrosoft.com' 连接时,它只会获得一个 AAD 图形令牌和一个 Microsoft Graph 令牌。没有用于调用 SFB 的令牌。所以根据我的研究,Get-CsTeamsCallingPolicy 不能这样调用。如果您有任何不清楚的地方,请随时告诉我。
  • 由于 Microsoft 一直声称 "SFBO cmdlet 现在已集成到 Teams Powershell 模块中" here,因此人们会假设 Get-CsTeamsCallingPolicy 是 Teams 模块的一部分,但显然 SFBO 和 Teams 模块之间仍然存在集成问题。
  • @kshab 是的。我同意你的看法。有什么不清楚的吗?如果我的回答有帮助,您可以将其标记为已接受。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 2011-09-19
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多