问题
当我在Python中收到来自Azure AD的JWK时,我想要验证并解码它。然而,我一直收到"签名验证失败"的错误。
我的设置
我的设置如下:
- Azure设置
在Azure中,我创建了一个应用程序注册,并选择了"仅适用于个人Microsoft帐户"的设置。 - Python设置
在Python中,我使用MSAL软件包接收令牌。我使用来自Azure的公钥来验证令牌。
代码
使用来自Azure门户的凭据,我设置了一个客户端以获取令牌。
import msal
ad_auth_client = msal.ConfidentialClientApplication(
client_id = client_id,
client_credential = client_secret,
authority = "https://login.microsoftonline.com/consumers"
)
my_token = ad_auth_client.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])
如果我将令牌抛到像https://jwt.io/这样的网站上,一切看起来都很好。接下来,我需要从Azure获取公钥以验证令牌。
import requests
response = requests.get("https://login.microsoftonline.com/common/discovery/keys")
keys = response.json()['keys']
为了将公钥与令牌匹配,我使用令牌头中的“kid”。我还获取了用于加密的算法。
import jwt
token_headers = jwt.get_unverified_header(my_token['access_token'])
token_alg = token_headers['alg']
token_kid = token_headers['kid']
public_key = None
for key in keys:
if key['kid'] == token_kid:
public_key = key
现在我已经从Azure获取了正确的公钥来验证我的令牌,但问题是它是一个JWT密钥。在我能用它进行解码之前,需要将其转换为RSA PEM密钥。
from cryptography.hazmat.primitives import serialization
rsa_pem_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(public_key))
rsa_pem_key_bytes = rsa_pem_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
这是 Azure 公钥的外观:
b'-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyr3v1uETrFfT17zvOiy0\n1w8nO+1t67cmiZLZxq2ISDdte9dw+IxCR7lPV2wezczIRgcWmYgFnsk2j6m10H4t\nKzcqZM0JJ/NigY29pFimxlL7/qXMB1PorFJdlAKvp5SgjSTwLrXjkr1AqWwbpzG2\nyZUNN3GE8GvmTeo4yweQbNCd+yO/Zpozx0J34wHBEMuaw+ZfCUk7mdKKsg+EcE4Z\nv0Xgl9wP2MpKPx0V8gLazxe6UQ9ShzNuruSOncpLYJN/oQ4aKf5ptOp1rsfDY2IK\n9frtmRTKOdQ+MEmSdjGL/88IQcvCs7jqVz53XKoXRlXB8tMIGOcg+ICer6yxe2it\nIQIDAQAB\n-----END PUBLIC KEY-----\n'
我需要做的最后一件事是使用公钥验证令牌。
decoded_token = jwt.decode(
my_token['access_token'],
key=rsa_pem_key_bytes,
verify=True,
algorithms=[token_alg],
audience=[client_id],
issuer="https://login.microsoftonline.com/consumers"
)
我收到的结果是:
jwt.exceptions.InvalidSignatureError: Signature verification failed
我也尝试过的方法
我还尝试了这个流行指南:如何验证由MS Azure AD生成的JWT id_token? 将x5c放入证书前后缀中会产生无效格式错误。
接下来是什么?
你们能看到明显的错误吗?我主要猜测是受众或发行者出了问题,但我无法确定是什么问题,而微软的文档像往常一样很差。此外,在Azure的应用注册中有一个秘密密钥,但它似乎也不起作用。
更新
结果发现我的验证代码是正确的,但我试图验证错误的令牌。稍作修改后,我现在收到了一个可以解码和验证的id_token。
jwt.InvalidAudienceError
。但是受众参数是可选的,因此在测试时将其删除并查看结果。 - jps