简体   繁体   English

验证来自 AAD Azure 的 JWT access_token 失败

[英]Validate JWT access_token from AAD Azure Fails

I need to validate a azure jwt access_token from the service I'm working on.我需要从我正在处理的服务中验证一个 azure jwt access_token。 We are currently making a request to https://graph.microsoft.com/beta/me .我们目前正在向https://graph.microsoft.com/beta/me发出请求。 If the request succeeded, the token is valid.如果请求成功,则令牌有效。 Unfortunately we will not be able to keep doing that.不幸的是,我们将无法继续这样做。

I have tried a variety of ideas for this.为此,我尝试了各种想法。 None of them with success.他们都没有成功。 Even jwt.io does not recognize the signature, even though jwt kid and the kid from one of the available signatures in jwk_uri matches.即使jwt.io不认签名,即使智威汤逊kidkid从可用的签名之一jwk_uri匹配。

Based on this blog post I have created a following solution (also available on github) .在此基础上博客我已经创建了一个下面的解决方案(也GitHub上可用)

My implementation is very similar to the blog post with a few changes:我的实现与博客文章非常相似,但有一些变化:

#!/usr/bin/env python2

import jwt
import requests
import sys

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


def get_public_key(access_token):
    """ Retrieve public key for access token """
    token_header = jwt.get_unverified_header(access_token)

    res = requests.get('https://login.microsoftonline.com/common/.well-known/openid-configuration')
    jwk_uri = res.json()['jwks_uri']

    res = requests.get(jwk_uri)
    jwk_keys = res.json()

    x5c = None
    # Iterate JWK keys and extract matching x5c chain
    for key in jwk_keys['keys']:
        if key['kid'] == token_header['kid']:
            x5c = key['x5c']
            break
    else:
        raise Exception('Certificate not found in {}'.format(jwk_uri))

    cert = ''.join([
        '-----BEGIN CERTIFICATE-----\n',
        x5c[0],
        '\n-----END CERTIFICATE-----\n',
    ])
    try:
        public_key =  load_pem_x509_certificate(cert.encode(), default_backend()).public_key()
    except Exception as error:
        raise Exception('Failed to load public key:', error)

    return public_key, key['kid']

def main():
    print '\n'
    if len(sys.argv) < 2 or '-h' in sys.argv:
        print 'Run it again passing acces token:\n\tpython jwt_validation.py <access_token>'
        sys.exit(1)

    access_token = sys.argv[1]
    audience = 'https://graph.microsoft.com'

    public_key, kid = get_public_key(access_token)

    try:
        jwt.decode(
            access_token,
            public_key,
            algorithms='RS256',
            audience=audience,
        )
    except Exception as error:
        print 'key {} did not worked, error:'.format(kid), error
        sys.exit(1)

    print('Key worked!')

if __name__ == '__main__':
    main()

This solution returns Invalid Signature for a valid access_token with the following traceback:此解决方案为具有以下追溯的有效 access_token 返回Invalid Signature

Traceback (most recent call last):
File "jwt_validation/jwt_validation.py", line 63, in <module>
    main()
File "jwt_validation/jwt_validation.py", line 57, in main 
    audience=audience,
File "~/.pyenv/versions/jwt-validation-tool/lib/python2.7/site-packages/jwt/api_jwt.py", line 93, in decode
    jwt, key=key, algorithms=algorithms, options=options, **kwargs
File "~/.pyenv/versions/jwt-validation-tool/lib/python2.7/site-packages/jwt/api_jws.py", line 157, in decode
    key, algorithms)
File "~/.pyenv/versions/jwt-validation-tool/lib/python2.7/site-packages/jwt/api_jws.py", line 224, in _verify_signature
    raise InvalidSignatureError('Signature verification failed')
jwt.exceptions.InvalidSignatureError: Signature verification failed

Any ideas of what I could be wrong would be helpful.关于我可能出错的任何想法都会有所帮助。

I ran into simillar issue, after couple of days investigating I've found in my case that I am requesting token with built in scopes (openid and profile) and without any custom scope which results in issuing tokens with different audiance (MS Graph) and hence tokens signed with with different public key (because I think that issued access_token is just a forward of the delegated MS Graph scope).我遇到了类似的问题,经过几天的调查,我发现在我的案例中,我正在请求具有内置范围(openid 和配置文件)的令牌,并且没有任何自定义范围,这导致发布具有不同受众的令牌(MS Graph)和因此用不同的公钥签名的令牌(因为我认为发出的 access_token 只是委托的 MS Graph 范围的一个转发)。

I resolved the issue by adding a custom scope in my app registration (Expose API section) and now my access_tokens are issued with valid audiance and I am able to check signature with my app public key.我通过在我的应用程序注册(公开 API 部分)中添加一个自定义范围解决了这个问题,现在我的 access_tokens 以有效的受众发布,我可以用我的应用程序公钥检查签名。

Usually the audience claim is used to point to the client_id of the client application you have registered in Azure/Microsoft.通常, audience声明用于指向您在 Azure/Microsoft 中注册的客户端应用程序的client_id Looks to me that the error is occurring due to a mismatch of claims in jwt (probably audience).在我看来,错误是由于jwt (可能是受众)中的声明不匹配而发生的。 Check whether you have set the correct client_id for the audience variable.检查您是否为受众变量设置了正确的client_id

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

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