使用 PyJWT 在 Python 中解码 Firebase JWT

Posted

技术标签:

【中文标题】使用 PyJWT 在 Python 中解码 Firebase JWT【英文标题】:Decode Firebase JWT in Python using PyJWT 【发布时间】:2021-11-17 23:58:57 【问题描述】:

我写了以下代码:

def check_token(token):
    response = requests.get("https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com")
    key_list = response.json()
    decoded_token = jwt.decode(token, key=key_list, algorithms=["RS256"])
    print(f"Decoded token : decoded_token")

我正在尝试解码 firebase 客户端提供的 token 以在服务器端进行验证。 上面的代码抛出了以下异常:

TypeError: Expecting a PEM-formatted key.

我试图不将列表传递给jwt.decode 方法,只传递关键内容,并且我有一个比库could not deserialize the Key 更大的错误。 我正在关注这个answer,但我收到了这个错误。

requests 转换问题吗?我做错了什么?

【问题讨论】:

【参考方案1】:

decode() 中的第二个参数key 似乎采用字符串值而不是列表。 Google API 请求返回一个包含多个键的 dict/map。流程是这样的:

    从 Google API 端点获取公钥 然后read headers without validation 获取kid 声明,然后使用它从该字典中获取适当的密钥 这是X.509 Certificate,而不是this answer 中的公钥,因此您需要从中获取公钥。

以下功能对我有用:

import jwt
import requests
from cryptography.hazmat.backends import default_backend
from cryptography import x509

def check_token(token):
    n_decoded = jwt.get_unverified_header(token)
    kid_claim = n_decoded["kid"]

    response = requests.get("https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com")
    x509_key = response.json()[kid_claim]
    key = x509.load_pem_x509_certificate(x509_key.encode('utf-8'),  backend=default_backend())
    public_key = key.public_key()

    decoded_token = jwt.decode(token, public_key, ["RS256"], options=None, audience="<FIREBASE_PROJECT_ID>")
    print(f"Decoded token : decoded_token")

check_token("FIREBASE_ID_TOKEN")

【讨论】:

感谢它工作正常!请求的 url 怎么样,当这个 url 改变时会通知开发者吗?我不喜欢它会改变并阻止所有请求的场景...... 它不应该改变(至少过于频繁)。我希望在它更改 tbh 之前得到事先通知,但最好通过支持@Tom3652 确认

以上是关于使用 PyJWT 在 Python 中解码 Firebase JWT的主要内容,如果未能解决你的问题,请参考以下文章

使用 PyJWT 的 Jwt 解码引发签名验证失败

pyJWT

PYJWT

在 Python 中使用来自 Gravitee 的公钥解码 JWT 令牌时出现问题

如何使用 pyJWT 验证此 JWT 上的签名?

Firebase JWT 库无法验证 Python JWT 令牌