简体   繁体   English

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

[英]How to validate a JWT from AzureAD in python?

I have set up an authorization server using AzureAD.我已经使用 AzureAD 设置了授权服务器。 For testing it I am currently applying an implicit flow and to get a token and id_token I use https://oidcdebugger.com/ .为了测试它,我目前正在应用隐式流并获取令牌和 id_token 我使用https://oidcdebugger.com/

Now I am trying to figure out how to properly validate a the token on the resource server side.现在我想弄清楚如何正确验证资源服务器端的令牌。 I always get a jose.exceptions.JWTError: Signature verification failed .我总是收到jose.exceptions.JWTError: Signature verification failed Can you help me find out what I am doing wrong?你能帮我找出我做错了什么吗? I am really new to JWT validation and probably there is some obvious error somwhere.我对 JWT 验证真的很陌生,可能在某个地方存在一些明显的错误。

As defined by the OIDC metadata endpoint at https://login.microsoftonline.com/{tenant_id}/v2.0/.well-known/openid-configuration keys for signature validation can be found at https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys .https://login.microsoftonline.com/{tenant_id}/v2.0/.well-known/openid-configuration的 OIDC 元数据端点所定义,用于签名验证的密钥可在https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys The key ids on that endpoint match the kid value in my token headers.该端点上的密钥 ID 与我的令牌标头中的kid值匹配。 So, I am positive that those are my keys.所以,我很肯定这些是我的钥匙。 They look like this:它们看起来像这样:

{
   "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"
}

In the answer of this post the key is constructed by hand using cryptography.x509 .这篇文章的答案中,密钥是使用cryptography.x509手工构建的。 I tried the same but I had to change a few details to make it run.我尝试了同样的方法,但我必须更改一些细节才能使其运行。 I am .encode ing the string and I have to pass an iterable to the decode function.我是.encode字符串,我必须将一个可迭代传递给decode function。

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])

It seems like I am not supposed to validate the (access) token, only the id_token signature.似乎我不应该验证(访问)令牌,只验证 id_token 签名。 The validation with jose also works by just supplying the key dict as keys argument (no need to construct certificate).使用jose的验证也可以通过仅提供密钥 dict 作为keys参数来工作(无需构造证书)。

Apparently the (access) token from AzureAD is not necessarily a standard JWT.显然,来自 AzureAD 的(访问)令牌不一定是标准的 JWT。 It's just supposed to be used for accessing the MS GraphAPI: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264它只应该用于访问 MS GraphAPI: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM