【问题标题】:How to verify JWT id_token produced by MS Azure AD?如何验证 MS Azure AD 生成的 JWT id_token?
【发布时间】:2017-08-25 20:17:39
【问题描述】:

我有一个使用 ADAL-JS(和 adal-angular)的 angularjs SPA 网络应用程序。 它设置为与我们在 MS Azure 中的公司 AD 进行身份验证。登录流程似乎工作正常,并且 SPA 收到了一个 id_token。

接下来,当用户单击按钮时,SPA 会向我在 AWS API Gateway 上托管的 REST API 发出请求。我在 Authorization: Bearer <id_token> 标头上传递 id_token。 API 网关按预期接收标头,现在必须确定给定令牌是否有效,以允许或拒绝访问。

我有一个示例令牌,它可以在 https://jwt.io/ 上正确解析,但到目前为止我还没有找到我应该用来验证签名的公钥或证书。我看过了:

认为我应该使用https://login.microsoftonline.com/common/discovery/keys 中键的 x5c 属性的值来匹配 JWT id_token 中的 Kid 和 x5t 属性(当前为 a3QN0BZS7s4nN-BdrjbF0Y_LdMM,这会导致 x5c 值以“MIIDBTCCAe2gAwIBAgIQY...”开头)。但是,https://jwt.io/ 页面报告“无效签名”(我还尝试使用“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”包装密钥值)。

此外,是否有一个(可能是 python)库可以方便验证给定的 id_token,如上述情况(这样我就不必自己去获取签名密钥了?)...我能找到的最好的 (ADAL for python) 似乎没有提供此功能?

【问题讨论】:

  • 你见过this
  • 嘿@4c74356b41 - 感谢您的链接!可能很方便,但是..我看不到该库中的令牌签名在哪里检查?

标签: python azure jwt adal


【解决方案1】:

到目前为止我能想到的最好的解决方案:

https://login.microsoftonline.com/common/discovery/keyshttps://login.microsoftonline.com/common/discovery/v2.0/keys 获取证书x5c 属性数组中的第一个值),匹配来自 id_token 的kidx5t

将证书包装-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE----- 中(换行符似乎很重要),并将结果用作公钥(与https://jwt.io/ 上的id_token 一起使用)。

当然,您的实际用例可能是让某些程序验证传入的 JWT id_tokens,因此您的目标不是简单地通过https://jwt.io/ 上的 Web UI 获取令牌以进行验证。

例如,在python中,我需要这样的东西:

#!/usr/bin/env python

import jwt
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

PEMSTART = "-----BEGIN CERTIFICATE-----\n"
PEMEND = "\n-----END CERTIFICATE-----\n"

mspubkey = "The value from the x5c property"
IDTOKEN = "the id_token to be validated"
tenant_id = "your tenant id"

cert_str = PEMSTART + mspubkey + PEMEND
cert_obj = load_pem_x509_certificate(cert_str, default_backend())
public_key = cert_obj.public_key()

decoded = jwt.decode(IDTOKEN, public_key, algorithms=['RS256'], audience=tenant_id)
if decoded:
    print "Decoded!"
else:
    print "Could not decode token."

有关各种语言的 JWT 库列表,请参阅the JWT Site。 我正在使用pyjwt 及其cryptography 依赖项(它具有二进制依赖项,因此需要为目标操作系统构建和打包)。

然后,当然,您可以验证其他详细信息,例如声明recommended here

【讨论】:

  • 我以前从未编写过 python 代码。根据我的理解,您不应该这样做,因为 Azure AD 使用的签名密钥可以非常频繁地滚动,并且从今年开始微软甚至不会通知,因为期望程序/应用程序可以无缝处理它。见下文docs.microsoft.com/en-us/azure/active-directory/develop/…
  • @Gopi Kolla 你是绝对正确的。事实上,除了这个初始代码(旨在弄清楚令牌验证如何工作)之外,我已经获取了 MS 公钥(按每日计划,因为他们建议每 24 小时检查一次)并保存它们我可以按需使用它们。但我很感兴趣......如果一个人不应该完成我一直盯着的所有工作(并慢慢减少)......如何使用 MS Azure AD 进行身份验证而不是成为 .NET 应用程序(在 Azure 上运行)?
  • 我在查询 login.microsoftonline.com/common/discovery/keys 时得到 2 个密钥。我怎么知道要使用哪个键?在我解码令牌后,我可以在标题中看到 x5t,但那是在解码之后。我应该尝试两者,看看哪个成功?
  • @sargeMonkey 在此处查看“令牌验证”:francescorizzi.github.io/AWSomesauce/articles/BAS4-pws/…“在列出的键中,找到一个与要验证的令牌中的孩子值匹配的孩子(和 x5t)属性”和代码( TokenValidator) 在github.com/FrancescoRizzi/AWSomesauce/blob/master/articles/…
  • 我收到错误 TypeError: from_buffer() cannot return the address of a unicode object。我相信,问题在于声明cert_obj = load_pem_x509_certificate(cert_str, default_backend())
【解决方案2】:

对于 JVM 解决方案,使用 com.nimbusds:numbus-jose-jwt:4.29 是解析和验证签名 RSA256 id_token 的最直接方法。以下 Scala 代码使用 JSON Web Key 解析 JWT 令牌:

    val jwt = SignedJWT.parse(token)

    val n = new Base64URL("Your Modulus Component of RSA Key")
    val e = new Base64URL("AQAB")
    val rsaKey = new RSAKey.Builder(n, e).keyUse(KeyUse.SIGNATURE).algorithm(JWSAlgorithm.RS256).build()

    val verified = jwt.verify(new RSASSAVerifier(rsaKey))

您的应用程序仍需要从 Azure Active Directory B2C discovery/v2.0/key 动态获取 JSON Web 密钥集,以获取 AAD B2C 可能使用的密钥集。这可能应该被缓存并具有不超过 24 小时的 TTL 以提高效率。

【讨论】:

    【解决方案3】:

    此外,是否有一个(可能是 python)库可以方便验证给定的 id_token,如上述情况(这样我就不必自己去获取签名密钥了?)...我能找到的最好的(用于 python 的 ADAL)似乎没有提供这个功能?

    对于它的价值,ADAL Python 的继任者 MSAL Python 在后台验证 id 令牌,并为您的应用程序验证 provides you the decoded claims inside an id token。这样您的应用(刚刚通过 MSAL Python 获得该 id 令牌)就可以在本地使用它。

    接下来,当用户单击按钮时,SPA 会向我在 AWS API Gateway 上托管的 REST API 发出请求。我在 Authorization: Bearer <id_token> 标头上传递 id_token。 API 网关按预期接收标头,现在必须确定给定令牌是否有效,以允许或拒绝访问。

    通常不会在“Authorization: Bearer <id_token> 标头”上使用 id 令牌发送给第 3 方以进行授权。 YMMV。

    【讨论】:

    • 这对 OP 的问题有效吗?听起来他们正在获取 FE 客户端库提供的令牌,将其发送到需要验证的 BE。我遇到了类似的难题:使用@azure/msal-react 客户端并需要发送到 Django/DRF 服务器以验证令牌是否有效并且它属于发送它的人。尚不清楚 MSAL Python 是否具有此功能,或者它是否适用于通过它检索的令牌。
    猜你喜欢
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 2021-08-21
    • 2016-12-02
    • 2020-08-12
    • 2019-08-28
    相关资源
    最近更新 更多