如何在 python 中验证来自 AzureAD 的 JWT?

Posted

技术标签:

【中文标题】如何在 python 中验证来自 AzureAD 的 JWT?【英文标题】:How to validate a JWT from AzureAD in python? 【发布时间】:2020-11-21 11:48:41 【问题描述】:

我已经使用 AzureAD 设置了授权服务器。 为了测试它,我目前正在应用一个隐式流并获取一个令牌和 id_token 我使用https://oidcdebugger.com/。

现在我正在尝试弄清楚如何在资源服务器端正确验证令牌。 我总是收到jose.exceptions.JWTError: Signature verification failed。 你能帮我找出我做错了什么吗? 我对 JWT 验证真的很陌生,可能在某些地方存在一些明显的错误。

由 OIDC 元数据端点在 https://login.microsoftonline.com/tenant_id/v2.0/.well-known/openid-configuration 键 签名验证可以在 https://login.microsoftonline.com/tenant_id/discovery/v2.0/keys。 该端点上的密钥 ID 与我的令牌标头中的 kid 值匹配。 所以,我很肯定这些是我的钥匙。 它们看起来像这样:


   "kty": "RSA",
   "use": "sig",
   "kid": "<the-key-id>",
   "x5t": "<the-key-id>",
   "n": "<a-long-hash>",
   "e": "AQAB",
   "x5c": ["<a-long-hash-I-guess-thats-the-public-key"],
   "issuer": "https://login.microsoftonline.com/<my-tenant-id>/v2.0"

在this post 的答案中,密钥是使用cryptography.x509 手动构造的。 我尝试了同样的方法,但我必须更改一些细节才能使其运行。 我是.encodeing 字符串,我必须将一个可迭代对象传递给decode 函数。

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

AZURE_TENANT_ID = '<my-tenant-id>'
AZURE_KEYS = requests.get(url='<my-jwks_url>').json()['keys']

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


def decode(token: str, keys: list):
    token_header = jwt.get_unverified_header(token=token)
    x5t = token_header['x5t']

    key = [d for d in keys if d['x5t'] == x5t][0]
    mspubkey = key['x5c'][0]

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

    return jwt.decode(
        token=token,
        subject='<my-subject>',
        audience='<my-audience>',
        issuer=f'https://sts.windows.net/AZURE_TENANT_ID/',
        algorithms=['RS256'],
        key=[public_key])

【问题讨论】:

【参考方案1】:

似乎我不应该验证(访问)令牌,只验证 id_token 签名。使用jose 进行验证也可以通过将密钥字典作为keys 参数提供(无需构造证书)。

显然,来自 AzureAD 的(访问)令牌不一定是标准 JWT。它应该只是用于访问 MS GraphAPI:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264

【讨论】:

以上是关于如何在 python 中验证来自 AzureAD 的 JWT?的主要内容,如果未能解决你的问题,请参考以下文章

openid connect owin 如何验证来自 Azure AD 的令牌?

如何在后端 API 中验证 AzureAD accessToken

如何使 AzureAD 和自定义 JWT 令牌在 Web API 中并行工作?

Azure AD 在 Web API 中使用来自客户端应用程序的令牌

如何将“AzureAd”详细信息显式传递给 AddMicrosoftIdentityWebApi 方法以进行令牌验证

如何使用 Python 在 Azure AD 中验证令牌