从AAD Azure验证JWT access_token失败



我需要验证我正在处理的服务中的azure jwt access_token。我们目前正在向https://graph.microsoft.com/beta/me.如果请求成功,则令牌有效。不幸的是,我们将无法继续这样做。

为此,我尝试了各种各样的想法。他们都没有成功。即使jwt.io也不识别签名,即使jwt-kid和jwk_uri中可用签名之一的kid匹配。

基于这篇博客文章,我创建了以下解决方案(也可在github上获得(。

我的实现与博客文章非常相似,只是做了一些更改:

#!/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:ntpython 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()

此解决方案通过以下回溯返回有效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

任何关于我可能错的想法都会有所帮助。

我遇到了类似的问题,经过几天的调查,我发现在我的案例中,我正在请求具有内置作用域(openid和profile(且没有任何自定义作用域的令牌,这会导致发行具有不同听觉的令牌(MS Graph(,从而使用不同公钥签名的令牌(因为我认为发行的access_token只是委托的MS Graph作用域的转发(。

我通过在我的应用程序注册中添加一个自定义作用域(公开API部分(来解决这个问题,现在我的access_token被颁发了有效的音频,我可以用我的应用公共密钥检查签名。

通常audience声明用于指向您在Azure/Microsoft中注册的客户端应用程序的client_id。在我看来,错误的发生是由于jwt中的声明不匹配(可能是受众(。检查是否为访问群体变量设置了正确的client_id

相关内容

最新更新