如何验证MS Azure AD生成的JWT id_token?

FOR*_*FOR 11 python azure jwt adal

我有一个angularjs SPA网络应用程序,它使用ADAL-JS(和adal-angular).它设置为在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)似乎没有提供此功能?

FOR*_*FOR 17

到目前为止我可以组合的最佳解决方案:

抓斗的证书(中的第一个值x5c从任一属性阵列)https://login.microsoftonline.com/common/discovery/keyshttps://login.microsoftonline.com/common/discovery/v2.0/keys,匹配kidx5t从id_token.

裹在证书-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----(新行似乎没有问题),以及(与id_token结合,对使用结果作为公钥https://jwt.io/).

当然,您的实际用例可能是让某些程序验证传入的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."
Run Code Online (Sandbox Code Playgroud)

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

然后,当然,你可以验证其他细节,如索赔建议在这里.

  • 我以前从未编码过python。根据我的理解,您不应该这样做,因为 Azure AD 使用的签名密钥可以非常频繁地滚动,并且从今年开始,Microsoft 甚至没有通知,因为期望程序/应用程序可以无缝处理它。请参阅以下 https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-signing-key-rollover (2认同)
  • 当我查询 https://login.microsoftonline.com/common/discovery/keys 时,我得到 2 个密钥。我如何知道使用哪个键?解码令牌后,我可以在标头中看到 x5t,但那是解码后的。我应该同时尝试两者并看看哪个成功吗? (2认同)
  • @sargeMonkey 请参阅此处的“令牌验证”:https://francescorizzi.github.io/AWSomesauce/articles/BAS4-pws/index.html“在列出的键中,找到一个与kid值匹配的kid(和x5t)属性来自要验证的令牌”和 https://github.com/FrancescoRizzi/AWSomesauce/blob/master/articles/BAS4-pws/custauth/custauth.py 中的代码 (TokenValidator) (2认同)
  • 我收到错误“TypeError: from_buffer() 无法返回 unicode 对象的地址”。我相信,问题在于语句 `cert_obj = load_pem_x509_certificate(cert_str, default_backend())` (2认同)