在基于 Azure AD 的多租户应用程序中代表用户获取令牌 - 未配置访问用户信息的权限?
Obtaining a token on behalf of a user in a multi-tenanted, azure AD based application - No permission to access user information is configured?
我目前正在为一系列基于云的微服务制作身份验证模型的原型,并且在尝试代表经过身份验证的用户从 Azure AD 获取令牌时遇到了 运行 障碍。我觉得我遗漏了一些明显的东西,所以我希望有人能指出正确的方向。
概览
我的原型包含两个应用程序:
- 一个Asp.MVC基地UI
- 基于 WebAPI 的数据服务。
这两个应用程序都托管在 Azure 中,并使用 Azure 的活动目录进行访问管理。在 azure 中,我设置了两个 AD 实例:
- 服务目录:这是注册所有应用程序的主目录。
- 租户目录:租户的AD实例。今后,每个租户都会有其中之一。
UI 和数据服务都在服务目录中注册并设置为多租户。 UI 身份验证基于 Vibronet's multi-tenant sample 并在用户首次登录时正确推送用户通过许可授予流程,然后向用户 AD 实例注册 UI 应用程序。在同意授予期间,UI 请求以下权限:
- 访问您组织的目录
- 启用登录并读取用户的个人资料
- 读写目录数据
- 读取目录数据
然后用户被重定向回 UI 应用程序,此时我可以成功查看用户的索赔信息。所以,到目前为止,我相信一切都已配置并正常工作。
问题
用户通过身份验证后,UI 应用程序应代表当前用户获取令牌以访问后端数据服务,这就是问题所在。
数据服务的身份验证基于 WebApi-On-Behalf-of 示例,但是每当我尝试获取令牌时,我都会收到以下错误:
[AppGuid]应用未配置访问用户信息的权限,或已过期或撤销
然而,考虑到在同意流程中授予的权限,我认为它应该有权访问租户 AD 实例,并已尝试向 UI 应用程序提供 AD 中可用的所有应用程序和委派权限,并重新运行启用同意流程但仍然得到相同的结果。
我获取代币的代码如下:
ClientCredential uICredentials = new ClientCredential(StartUp.UiClientId, StartUp.UiSecret);
BootstrapContext bootStrapContext = GetBootstrapContext();
UserAssertion userAssertion = new UserAssertion(bootStrapContext.Token);
AuthenticationContext authContext = new AuthenticationContext(StartUp.adAuthority);
var authResult = authContext.AcquireToken(routerServiceResourceId, uICredentials, userAssertion);
在最后一行出现异常。这里的参数是:
- StartUp.UiClientId: 服务目录中 UI 的应用程序 ID。
- StartUp.UiSecret:服务目录中UI应用程序的密钥。
- StartUp.adAuthority:我已经尝试使用多租户应用程序的通用 AD 端点 (https://login.microsoftonline.com/common/) and with the specific endpoint for this tenant (https://login.microsoftonline.com/tenantid)。两者给出相同的结果。
- routerServiceResourceId:数据服务的 App Id URI。
此外,我在 UI 应用程序的 TokenValidationParameters 中将 'SaveSigninToken' 设置为 true,这样我就可以获得 BootstrapContext.Token.
据我所知,这就是它应该工作所需的一切,但正如我所说,我不断收到上面的错误 =/
任何人都可以为此提出前进的方向/明显的解决方案/进一步阅读。我似乎在努力反对这一点,但并没有走得太远。关于这个问题,我也不是 100% 了解什么信息是相关的,所以如果我遗漏了任何重要的要点,请告诉我,我可以更新问题。
在这种情况下,流量的 OnBehalf 并不合适。当 WebAPI 收到访问令牌并需要为下游 WebAPI 获取访问令牌时,OnBehalf 流是合适的。最适合您的情况的流程是 OpenID Connect 代码+id_token 流程。在此流程中,WebApp 接收一个 id_token 来验证用户和一个授权代码,允许 WebApp 获取后端服务器的访问令牌。然后 WebApp 兑换访问令牌的授权代码。
此流程的最佳示例如下:
https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
注意Startup.Auth.cs设置AuthorizationCodeRecieved通知的地方。这显示了如何检索代码并兑换它。
我目前正在为一系列基于云的微服务制作身份验证模型的原型,并且在尝试代表经过身份验证的用户从 Azure AD 获取令牌时遇到了 运行 障碍。我觉得我遗漏了一些明显的东西,所以我希望有人能指出正确的方向。
概览
我的原型包含两个应用程序:
- 一个Asp.MVC基地UI
- 基于 WebAPI 的数据服务。
这两个应用程序都托管在 Azure 中,并使用 Azure 的活动目录进行访问管理。在 azure 中,我设置了两个 AD 实例:
- 服务目录:这是注册所有应用程序的主目录。
- 租户目录:租户的AD实例。今后,每个租户都会有其中之一。
UI 和数据服务都在服务目录中注册并设置为多租户。 UI 身份验证基于 Vibronet's multi-tenant sample 并在用户首次登录时正确推送用户通过许可授予流程,然后向用户 AD 实例注册 UI 应用程序。在同意授予期间,UI 请求以下权限:
- 访问您组织的目录
- 启用登录并读取用户的个人资料
- 读写目录数据
- 读取目录数据
然后用户被重定向回 UI 应用程序,此时我可以成功查看用户的索赔信息。所以,到目前为止,我相信一切都已配置并正常工作。
问题
用户通过身份验证后,UI 应用程序应代表当前用户获取令牌以访问后端数据服务,这就是问题所在。
数据服务的身份验证基于 WebApi-On-Behalf-of 示例,但是每当我尝试获取令牌时,我都会收到以下错误:
[AppGuid]应用未配置访问用户信息的权限,或已过期或撤销
然而,考虑到在同意流程中授予的权限,我认为它应该有权访问租户 AD 实例,并已尝试向 UI 应用程序提供 AD 中可用的所有应用程序和委派权限,并重新运行启用同意流程但仍然得到相同的结果。
我获取代币的代码如下:
ClientCredential uICredentials = new ClientCredential(StartUp.UiClientId, StartUp.UiSecret);
BootstrapContext bootStrapContext = GetBootstrapContext();
UserAssertion userAssertion = new UserAssertion(bootStrapContext.Token);
AuthenticationContext authContext = new AuthenticationContext(StartUp.adAuthority);
var authResult = authContext.AcquireToken(routerServiceResourceId, uICredentials, userAssertion);
在最后一行出现异常。这里的参数是:
- StartUp.UiClientId: 服务目录中 UI 的应用程序 ID。
- StartUp.UiSecret:服务目录中UI应用程序的密钥。
- StartUp.adAuthority:我已经尝试使用多租户应用程序的通用 AD 端点 (https://login.microsoftonline.com/common/) and with the specific endpoint for this tenant (https://login.microsoftonline.com/tenantid)。两者给出相同的结果。
- routerServiceResourceId:数据服务的 App Id URI。
此外,我在 UI 应用程序的 TokenValidationParameters 中将 'SaveSigninToken' 设置为 true,这样我就可以获得 BootstrapContext.Token.
据我所知,这就是它应该工作所需的一切,但正如我所说,我不断收到上面的错误 =/
任何人都可以为此提出前进的方向/明显的解决方案/进一步阅读。我似乎在努力反对这一点,但并没有走得太远。关于这个问题,我也不是 100% 了解什么信息是相关的,所以如果我遗漏了任何重要的要点,请告诉我,我可以更新问题。
在这种情况下,流量的 OnBehalf 并不合适。当 WebAPI 收到访问令牌并需要为下游 WebAPI 获取访问令牌时,OnBehalf 流是合适的。最适合您的情况的流程是 OpenID Connect 代码+id_token 流程。在此流程中,WebApp 接收一个 id_token 来验证用户和一个授权代码,允许 WebApp 获取后端服务器的访问令牌。然后 WebApp 兑换访问令牌的授权代码。
此流程的最佳示例如下:
https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
注意Startup.Auth.cs设置AuthorizationCodeRecieved通知的地方。这显示了如何检索代码并兑换它。