如何验证 Azure 活动目录中刷新的 id_token 的签名

Posted

技术标签:

【中文标题】如何验证 Azure 活动目录中刷新的 id_token 的签名【英文标题】:How to verify signature of refreshed id_token in Azure active directory 【发布时间】:2020-08-13 14:10:21 【问题描述】:

我们正在使用 Azure 活动目录 Oauth 代码流对用户进行身份验证。 我们使用代码获得了 access_token、id_token 和 refresh_token(在重定向 URL 上获得)。 认证成功后,我们使用 id_token 对每个请求进行授权,我们可以使用从/discovery/v2.0/keys api 获得的公钥来验证 JWT。

现在,JWT 将在 1 小时后过期。所以我们需要刷新这个 id_token。

我正在使用下面的 cURL 刷新 id_token

 curl --request POST \
  --url https://login.microsoftonline.com/tenant_id/oauth2/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data 'client_id=client%20id&refresh_token=refesh%20token%20&grant_type=refresh_token&client_secret=client_secret&scope=openid

在这个API的响应中,我们得到了access_token,refresh_token,id_token,但是如果你观察id_token,它不包含JWT签名(JWT的第三部分),没有签名我们无法验证JWT

我们找不到任何文档参考为什么 id_token 没有签名部分。 还有其他方法可以刷新 id_token 吗? 如果 id_token 无法刷新,有什么解决办法吗?

【问题讨论】:

【参考方案1】:

在某些情况下,可能会在没有签名的情况下返回 Id 令牌,特别是如果它是通过带有客户端密码的反向通道获取的。 您已经从权威机构通过加密通道获取令牌。 如果有人能够在那里注入一些东西,他们也将能够指导您的应用程序对 OpenID 元数据的请求,从而替换您的应用程序期望的签名密钥。 因此签名不会在这里增加太多价值。

此外,您不会将 Id 令牌发送到任何 API,因为 Id 令牌不应用于授权。 这就是访问令牌的用途:)

OpenID Connect 规范是这样说的:https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation

如果通过客户端和令牌端点(在此流程中)之间的直接通信接收到 ID 令牌,则可以使用 TLS 服务器验证来验证颁发者,而不是检查令牌签名。客户端必须使用 JWT alg 标头参数中指定的算法根据 JWS [JWS] 验证所有其他 ID 令牌的签名。客户端必须使用颁发者提供的密钥。

但是,有趣的是也提到了这一点:https://openid.net/specs/openid-connect-core-1_0.html#IDToken

ID 令牌必须使用 JWS 进行签名,并且可以选择分别使用 JWS 和 JWE 进行签名和加密,从而根据第 16.14 节提供身份验证、完整性、不可否认性和可选的机密性。如果 ID 令牌已加密,则必须对其进行签名然后加密,结果是嵌套 JWT,如 [JWT] 中所定义。 ID 令牌不得使用 none 作为 alg 值,除非使用的响应类型从授权端点返回没有 ID 令牌(例如在使用授权代码流时)并且客户端在注册时明确请求使用 none。

所以.. 可能是 Azure AD 不符合规范?

编辑:Azure AD 的 v1 端点在这方面不兼容。较新的 v2 端点完全兼容 OpenID Connect。

【讨论】:

谢谢,假设我在身份验证后将 access_token 发送到 UI 应用程序,现在用户应用程序会将 access_token 发送到我的后端应用程序。如何验证此 access_token?我无法使用此 access_token 调用图形 API,因为范围是 openid 您应该从您的 UI 应用程序中获取访问令牌吗?它们的范围应该是您 API 的有效范围。您的 API 可以验证访问令牌的签名,因为这些签名将始终被签名。 用 OpenID Connect 规范中的一些引用更新了我的答案。第一个讨论了 TLS 允许您在刷新场景中确认颁发者的事实。但规范还提到必须对 Id 令牌进行签名。因此,这样一来,Azure AD 可能会违反规范。 我与 Azure AD 团队的一位成员讨论过这个问题。这仅在使用 v1 令牌端点时的某些情况下发生。另一方面,v2 端点完全符合 OpenID,因此那里的 ID 令牌将始终被签名。 谢谢,在将端点更改为/oauth2/v2.0/token 后,我在 id_token 和 access_token 中获得了完整的 JWT。如何验证 access_token 的签名?或者我的应用程序应该只验证 id_token 的签名。

以上是关于如何验证 Azure 活动目录中刷新的 id_token 的签名的主要内容,如果未能解决你的问题,请参考以下文章

azure 移动服务活动目录身份验证 X-ZUMO-AUTH 令牌在注销后在邮递员中有效

可以将 hadoop-azure 配置为对 azure blob 使用活动目录(租户、appId、appSecret)身份验证吗

Azure 活动目录是不是容易受到 DoS 或 DDOS 攻击

使用 loginwithazureactivedirectory 和 expressmode 的 Azure 活动目录

如何从 azure 活动目录中删除应用程序?

请求 Azure 应用服务身份验证刷新令牌