首页 文章

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

提问于
浏览
6

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

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

我有一个示例令牌,它在https://jwt.io/上正确解析但我到目前为止未能找到我应该用来验证签名的公钥或证书 . 我查了一下:

我想我应该使用匹配来自JWT id_token的kid和x5t属性的https://login.microsoftonline.com/common/discovery/keys中的键的x5c属性的值(当前 a3QN0BZS7s4nN-BdrjbF0Y_LdMM ,这导致以"MIIDBTCCAe2gAwIBAgIQY..."开头的x5c值) . 但是,https://jwt.io/页报告"Invalid Signature"(我也尝试用"-----BEGIN CERTIFICATE-----"和"-----END CERTIFICATE-----"包装键值) .

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

2 回答

  • 12

    到目前为止我能把最好的解决方案放在一起:

    Grab the certificatex5c 属性数组中的第一个值)来自 https://login.microsoftonline.com/common/discovery/keyshttps://login.microsoftonline.com/common/discovery/v2.0/keys ,匹配来自id_token的 kidx5t .

    Wrap the certificate\n-----END CERTIFICATE----- 中的 Wrap the certificate (新行似乎很重要),并将结果用作公钥(与https://jwt.io/上的id_token一起使用) .

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

    例如, in 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依赖项(具有二进制依赖项,因此需要为目标操作系统构建和打包) .

    然后,当然,你可以 verify additional details such as the claimsrecommended here .

  • 1

    对于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可能使用的密钥集 . 这可能应该被缓存并且TTL不超过24小时以提高效率 .

相关问题