在 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 流程,并且我能够获取用户令牌并对图表进行调用,但我 运行 进入更改权限的问题。这是我所做的:
- 创建了一个机器人并给了它 mail.read
- 为用户添加机器人并触发 OAuth 对话框。提示用户同意并登录。
- 成功读取邮件
- 在 AAD 中,向应用程序添加了 Mail.ReadWrite 和 Mail.Send 权限
- 下次触发 OAuthPrompt 时,立即返回令牌。没有提示同意。
- 尝试编写或发送邮件时出现拒绝访问异常
所以问题是更改应用程序的权限不会自动在 OAuthPrompt 中再次触发同意流程。我还尝试了这些故障排除步骤:
- 我手动将用户注销 (botAdapter.SignOutUserAsync) 并重新登录,但系统没有再次提示我同意。
- 同上,但也退出了 Teams。以新的隐身方式启动 Web 客户端 window,但仍然没有提示同意。
- 已在用户帐户上卸载并重新安装机器人。没有变化。
- 等了几个小时后试了上面的方法,还是没有变化。
我发现再次触发同意流程的唯一方法是让用户转到 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 流程。)
我已经在类似于 sample 的 Teams 机器人中实现了 OAuth 流程,并且我能够获取用户令牌并对图表进行调用,但我 运行 进入更改权限的问题。这是我所做的:
- 创建了一个机器人并给了它 mail.read
- 为用户添加机器人并触发 OAuth 对话框。提示用户同意并登录。
- 成功读取邮件
- 在 AAD 中,向应用程序添加了 Mail.ReadWrite 和 Mail.Send 权限
- 下次触发 OAuthPrompt 时,立即返回令牌。没有提示同意。
- 尝试编写或发送邮件时出现拒绝访问异常
所以问题是更改应用程序的权限不会自动在 OAuthPrompt 中再次触发同意流程。我还尝试了这些故障排除步骤:
- 我手动将用户注销 (botAdapter.SignOutUserAsync) 并重新登录,但系统没有再次提示我同意。
- 同上,但也退出了 Teams。以新的隐身方式启动 Web 客户端 window,但仍然没有提示同意。
- 已在用户帐户上卸载并重新安装机器人。没有变化。
- 等了几个小时后试了上面的方法,还是没有变化。
我发现再次触发同意流程的唯一方法是让用户转到 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 流程。)