如何在 python 中验证来自 AzureAD 的 JWT?
How to validate a JWT from AzureAD in python?
我已经使用 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 与我的令牌 headers 中的 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"
}
在 的答案中,密钥是使用 cryptography.x509
手动构建的。
我尝试了同样的方法,但我不得不更改一些细节以使其成为 运行。
我正在 .encode
ing 字符串,我必须将一个可迭代对象传递给 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])
似乎我不应该验证(访问)令牌,只验证 id_token 签名。使用 jose
的验证也可以通过仅提供密钥字典作为 keys
参数(无需构建证书)来工作。
显然,来自 AzureAD 的(访问)令牌不一定是标准的 JWT。它只是应该用于访问 MS GraphAPI:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264
我已经使用 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 与我的令牌 headers 中的 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"
}
在 cryptography.x509
手动构建的。
我尝试了同样的方法,但我不得不更改一些细节以使其成为 运行。
我正在 .encode
ing 字符串,我必须将一个可迭代对象传递给 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])
似乎我不应该验证(访问)令牌,只验证 id_token 签名。使用 jose
的验证也可以通过仅提供密钥字典作为 keys
参数(无需构建证书)来工作。
显然,来自 AzureAD 的(访问)令牌不一定是标准的 JWT。它只是应该用于访问 MS GraphAPI:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-529537264