在 bot 框架 OAuth Flow with Teams 中,同意更改权限的正确方法是什么?

In the bot framework OAuth Flow with Teams, what is the correct way to consent to changed permissions?

我已经在类似于 sample 的 Teams 机器人中实现了 OAuth 流程,并且我能够获取用户令牌并对图表进行调用,但我 运行 进入更改权限的问题。这是我所做的:

所以问题是更改应用程序的权限不会自动在 OAuthPrompt 中再次触发同意流程。我还尝试了这些故障排除步骤:

我发现再次触发同意流程的唯一方法是让用户转到 https://account.activedirectory.windowsazure.com/r#/applications 并从那里删除同意。即使那样,我也不得不调用 botAdapter.SignOutUserAsync(因为机器人服务仍然返回具有旧权限的令牌)。一旦我这样做并再次触发 OAuth 提示,我就能够获得具有新触发权限的同意流程。

所以我的问题是,有没有更好的方法来处理这个问题?如果新版本的机器人需要新权限,Microsoft.Bot.Builder.Dialogs 的 OAuthPrompt 和机器人服务是否应该重新提示同意?

简答

Bot Framework 的 AAD v1 身份验证提供程序不够灵活,无法支持添加范围。

您可以切换到 AAD v2 提供程序并在 OAuth 连接设置中指定您的新范围。然后,如果您强制用户再次登录(在 SignOutUserAsync 之后),您将看到一个包含新范围的同意屏幕。要设置 AAD v2 提供程序,请参阅 adding authentication to a bot 上的 Bot Framework 文档,其中包含适用于 AAD v1 和 AAD v2 提供程序的步骤。

长答案

此行为的关键是 AAD v1 和 AAD v2 终结点如何以不同方式处理权限和同意。

v1 的问题

在 v1 中,AAD 应用程序注册中的权限(例如 Mail.Send)是 pre-registered。在 sign-in 期间,AAD 检查用户是否已经同意应用程序的任何范围

  • 如果是,AAD 将跳过同意屏幕并最终为已经同意的范围提供访问令牌
  • 如果否,AAD 会显示同意屏幕所有已注册范围,并最终为所有这些范围提供访问令牌

这解释了您所看到的行为。在您告诉 Bot Framework 忘记当前访问令牌(通过 SignOutUserAsync)并强制用户再次登录后,AAD 会看到用户之前已同意,因此它会跳过同意屏幕并为您提供一个新令牌旧瞄准镜。

那么如何为已经同意的用户添加权限,而不是强制用户删除对应用的同意? AAD 的登录端点有一个 optional prompt parameter,您可以将其设置为 prompt=consent。这将强制 AAD 显示同意屏幕,就好像用户之前没有同意一样,并且它将包含所有已注册的权限。因此,如果您尝试使用访问令牌并遇到 403 Forbidden 错误(或等效异常),您可以使用 prompt=consent.

引导用户完成登录流程

不幸的是,使用 Azure Bot 服务的 AAD v1 提供程序,您对登录名 URL 没有足够的控制权来动态设置 prompt 参数,因此没有简单的方法来做到这一点。

输入 v2

但还是有希望的! AAD v2 终结点具有更灵活的 adding scopes incrementally 方式。在 v2 中,对于委派权限,权限 而不是 在 AAD 应用程序注册中必须是 pre-registered。相反,您在登录 URL 的 scope 参数中指定范围。在 sign-in 期间,AAD 检查用户是否同意 您在 URL.

中指定的范围
  • 如果是,AAD 将跳过同意屏幕并最终为您指定的范围提供访问令牌
  • 如果否,AAD 会显示同意屏幕您指定的所有范围,并最终为所有这些范围提供访问令牌 .

无论哪种方式,您最终都会得到一个访问令牌,其中包含您在 URL 中指定的所有范围。

Bot Framework 使用您在 OAuth 连接设置中指定的范围设置 scope 参数。因此,如果您在那里添加一个新范围,那么下次用户登录时,他们将看到一个具有新权限的同意屏幕,您将获得一个具有新范围的访问令牌。 (注意:要 re-trigger sign-in,您仍然必须使用 SignOutUserAsync 将用户注销。否则,Bot Framework 将继续为您提供它已经拥有的访问令牌,而不是执行使用 AAD 的新 sign-in 流程。)