问题描述
在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端的文档中操作 “在开发人员门户中启用 OAuth 2.0 用户授权” 和 “从开发人员门户成功调用 API” 两步后,非常重要的一步就是在API中配置JWT验证策略 - “配置 JWT 验证策略,对请求进行预授权”。 当在API中配置JWT Policy时,如以下内容:
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> <openid-config url="https://login.partner.microsoftonline.cn/{aad-tenant}/v2.0/.well-known/openid-configuration" /> <required-claims> <claim name="aud"> <value>xxxxxxxx-xxxx-xxxx-xxxx-d322750988cb</value> </claim> </required-claims> </validate-jwt>
其中虽然携带了正确的Authorization Token,但是依旧还是会遇见 “IDX10205: Issuer validation failed. Issuer: 'https://sts.chinacloudapi.cn/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/'. Did not match: validationParameters.ValidIssuer: '' or validationParameters.ValidIssuers: 'https://login.partner.microsoftonline.cn/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0'." 错误。
问题原因
报错的原因是policy中openid-config url 使用的时OAuth 2.0 的 V2.0 版本而导致的。
- OAuth V1 终结点为:https://login.partner.microsoftonline.cn/{aad-tenant}/.well-known/openid-configuration, 它使用的Issuer为:https://sts.chinacloudapi.cn/{aad-tenant}/
- OAuth V2 终结点为:https://login.partner.microsoftonline.cn/{aad-tenant}/v2.0/.well-known/openid-configuration,它使用的Issuer为:https://login.partner.microsoftonline.cn/{aad-tenant}/v2.0
通过对比Openid-Configuration内容,就能发现其中的不同之处:
解析AAD所生成的Token值,就可以明确发现使用的是V1颁发。 解析Token可以使用在线工具:https://jwt.io/. 如:
所以,解决以上问题,可以有两种办法:
办法一:修改JWT Policy中设置 openid-config. 改为使用V1的终结点
办法二:修改Azure AD中注册应用的 accessTokenAcceptedVersion 为2
在Azure AD的应用注册页面的清单中(Manifest)修改 accessTokenAcceptedVersion的值,从null变为2.
{ "id": "79448457-d7a9-4b27-be7b-f70fd311e45f", "acceptMappedClaims": null, "accessTokenAcceptedVersion": null, "addIns": [], "allowPublicClient": true, ........ ###改变为 { "id": "79448457-d7a9-4b27-be7b-f70fd311e45f", "acceptMappedClaims": null, "accessTokenAcceptedVersion": 2, "addIns": [], "allowPublicClient": true, .......
操作截图:
附录:配置OAuth 2.0 的三个重要步骤
一:在 Azure AD 中授予权限
注册了用于表示 API 和开发人员控制台的两个应用程序之后,请授予权限以允许客户端应用调用后端应用。
- 转到 Azure 门户来向客户端应用程序授予权限。 搜索并选择“应用注册”。
- 选择你的客户端应用程序。 然后,在应用的页面列表中,选择“API 权限”。
- 选择“添加权限”。
- 在“选择 API”下,选择“我的 API”,然后找到并选择你的 backend-app。
- 在“委托的权限”下,选择对 backend-app 的适当权限,然后选择“添加权限”。
- (可选)在“API 权限”页上,选择“授予对 <your-tenant-name> 的管理员许可”,为此目录中的所有用户授予许可。
二:在开发人员门户中启用 OAuth 2.0 用户授权
此时,我们已在 Azure AD 中创建应用程序,并已授予适当的权限来让客户端应用调用后端应用。
在本示例中,开发人员控制台是 client-app。 以下步骤说明如何在开发人员门户中启用 OAuth 2.0 用户授权
- 在 Azure 门户中,浏览找到你的 API 管理实例。
- 选择“OAuth 2.0” > “添加”。
- 提供“显示名称”和“说明”。
- 对于“客户端注册页 URL”,请输入占位符值,如
http://localhost
。 “客户端注册页 URL”指向供用户针对 OAuth 2.0 提供程序创建和配置其自己的帐户的页面。 在此示例中,用户不创建和配置自己的帐户,因此使用了占位符。- 选择“授权代码”作为“授权类型”。
- 指定“授权终结点 URL”和“令牌终结点 URL”。 可以从 Azure AD 租户中的“终结点”页检索这些值。 再次浏览到“应用注册”页,并选择“终结点”。
- 复制“OAuth 2.0 授权终结点”,并将其粘贴到“授权终结点 URL”文本框。 选择“授权”请求方法下的“POST”。
- 复制“OAuth 2.0 令牌终结点”,并将其粘贴到“令牌终结点 URL”文本框。
重要
使用“v1”或“v2”终结点 。 但是,根据所选的版本,以下步骤将有所不同。 我们建议使用 v2 终结点。- 如果使用 v1 终结点,请添加名为 resource 的主体参数。 使用后端应用的“应用程序 ID”作为此参数的值。
- 如果使用 v2 终结点,请在“默认范围”字段中使用为后端应用创建的范围。 另外,确保在应用程序清单中将
accessTokenAcceptedVersion
属性的值设置为2
。- 接下来,指定客户端凭据。 这些是 client-app 的凭据。
- 对于“客户端 ID”,请使用客户端应用的“应用程序 ID”。
- 对于“客户端机密”,请使用前面为 client-app 创建的密钥。
- 紧接在客户端机密的后面,是授权代码授权类型的 redirect_url。 记下此 URL。
- 选择“创建” 。
- 返回到 Azure Active Directory 中的客户端应用注册,并选择“身份验证”。
- 在“平台配置”下,单击“添加平台”,然后选择“Web”作为类型,将“redirect_url”粘贴在“重定向 URI”下,然后单击“配置”按钮进行保存。
配置 OAuth 2.0 授权服务器后,开发人员控制台可从 Azure AD 获取访问令牌。
下一步是为 API 启用 OAuth 2.0 用户授权。 这使得开发人员控制台知道在调用 API 之前,需要代表用户获取访问令牌。
- 浏览到 API 管理实例,并转到“API”。
- 选择要保护的 API。 例如,
Echo API
。- 转到“设置”。
- 在“安全性”下,选择“OAuth 2.0”并选择前面配置的 OAuth 2.0 服务器。
- 选择“保存” 。
三: 配置 JWT 验证策略,对请求进行预授权
此时,当用户尝试从开发人员控制台发出调用时,系统会提示其登录。 开发人员控制台将代表用户获取访问令牌,并在对 API 发出的请求中包含该令牌。
但是,如果有人调用我们的 API 但未提供令牌或者提供无效的令牌,会发生什么情况? 例如,如果在不使用
Authorization
标头的情况下尝试调用 API,调用仍将继续。 原因是 API 管理暂时不会验证访问令牌。 它只是将Authorization
标头传递给后端 API。使用验证 JWT 策略通过验证每个传入请求的访问令牌,对 API 管理中的请求进行预授权。 如果某个请求没有有效的令牌,API 管理会阻止该请求。 例如,在
Echo API
的<inbound>
策略部分中添加以下策略。 它会检查访问令牌中的受众声明,如果令牌无效,则会返回一条错误消息。 有关如何配置策略的信息,请参阅设置或编辑策略。
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> <openid-config url="https://login.partner.microsoftonline.cn/{aad-tenant}/.well-known/openid-configuration" /> <required-claims> <claim name="aud"> <value>{Application ID of backend-app}</value> </claim> </required-claims> </validate-jwt>
备注
此
openid-config
URL 对应于 v1 终结点。 对于 v2openid-config
终结点,请使用以下 URL:
https://login.partner.microsoftonline.cn/common/v2.0/.well-known/openid-configuration
.
参考文档
在 Azure API 管理中使用 OAuth 2.0 授权和 Azure AD 保护 Web API 后端:https://docs.azure.cn/zh-cn/api-management/api-management-howto-protect-backend-with-aad