You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python解析AWS Cognito生成的JWT时出现Could not deserialize key data错误

AWS Cognito JWT在Python Lambda中解析失败

我有一个AWS Cognito生成的JWT Token,该Token已通过AWS API Gateway认证并成功调用后端AWS Lambda。这是一个有效JWT,在jwt.io上能正常解析,网关认证也没问题,但在Python版Lambda中无法解析。

代码片段

def decodeJWT(authHeader):
   jwt_token=authHeader.replace('Bearer ','')
   print(jwt_token)
   decoded_jwt=jwt.decode(jwt=jwt_token, algorithms="RS256")
   return decoded_jwt

传入的认证头

Bearer eyJraWQiOiJmUjFiZ21VdzhoNW9RUnZxeVUwZW9jbkhsSU1CbTNZMHRGS3oyVXFLNjVzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI0NTYzMWVlMy04MWEzLTQ3ZTMtYTEzMS0yNGRhNWY1MmYyMzIiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAudXMtZWFzdC0yLmFtYXpvbmF3cy5jb21cL3VzLWVhc3QtMl92YjB4dFBrVlciLCJ2ZXJzaW9uIjoyLCJjbGllbnRfaWQiOiI0MzRubm5nbTFrZnZvMGZtNHVtZzN2OGJ1ZCIsImV2ZW50X2lkIjoiMTVhNWNiMTktNjI0ZS00ZTk0LThiMjktMjI3MmFmYjE4Mjc5IiwidG9rZW5fdXNlIjoiYWNjZXNzIiwic2NvcGUiOiJhd3MuY29nbml0by5zaWduaW4udXNlci5hZG1pbiIsImF1dGhfdGltZSI6MTcwMTE4NjkwMCwiZXhwIjoxNzAxMTkwNTAwLCJpYXQiOjE3MDExODY5MDAsImp0aSI6IjY3M2Y2MTVlLWNmMWMtNDZjMC1iOWY0LTBkMjFiNWI1MThkOSIsInVzZXJuYW1lIjoidGVzdF9hIn0.BKdUHR_al5IAprfZHK9fEC7kthrv6kpyDXdsM6nrUQufVEMliIyz1dk3ruGhDDP4HjW8czlwegoYDX5aqrou3AkXWivsN8JplJELwb3li9XsHOrBhajLgHYwTUdEm5EFQcyxTD22IvkeByHokvzeOW1IakHIR_qdiH4zv9MNfjpy2svuS7imnnik1XLGx0A7eZmq6IDQlfu3v1Bk_ePBpgaOlZBEypmcIaZe5BySbZo6QrLfzASgwfMF0XrJYwtydgq3jz7L3EWEO1IaHT3x-qwZuOC8S4n3m0hr-PZwt7r3akXb75OlFbJMoWRuuWViC-Jpqzm3e72ueNc5BeSIBQ

已确认"Bearer "字符串已被移除,剩余JWT有效。

错误信息

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/jwt/algorithms.py", line 350, in prepare_key
    RSAPrivateKey, load_pem_private_key(key_bytes, password=None)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 25, in load_pem_private_key
    return ossl.load_pem_private_key(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 747, in load_pem_private_key
    return self._load_key(
           ^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 929, in _load_key
    self._handle_key_loading_error()
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 984, in _handle_key_loading_error
    raise ValueError(
ValueError: ('无法反序列化密钥数据。数据格式可能不正确、使用了不支持的算法加密,或是不支持的密钥类型(例如带显式参数的EC曲线)。', [<OpenSSLError(code=503841036, lib=60, reason=524556, reason_text=unsupported)>])

环境信息

  • Python 3.11.2
  • pip 23.3.1

解决方法

问题根源:使用jwt.decode时未提供RS256签名所需的公钥。AWS Cognito的JWT采用非对称加密签名,解析必须用对应的公钥验证,不能直接解析。

修正后的代码

import jwt
import requests

def get_cognito_public_keys(user_pool_id):
    # 从Cognito用户池获取公钥集合
    url = f"https://cognito-idp.us-east-2.amazonaws.com/{user_pool_id}/.well-known/jwks.json"
    response = requests.get(url)
    return response.json()["keys"]

def decodeJWT(authHeader):
    jwt_token = authHeader.replace('Bearer ', '')
    # 从JWT头部获取密钥ID(kid)
    header = jwt.get_unverified_header(jwt_token)
    kid = header["kid"]
    
    # 替换为你的Cognito用户池ID
    user_pool_id = "us-east-2_vb0xtPkVW"
    keys = get_cognito_public_keys(user_pool_id)
    
    # 匹配对应kid的公钥
    public_key = None
    for key in keys:
        if key["kid"] == kid:
            public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
            break
    
    if not public_key:
        raise ValueError("未找到匹配的公钥")
    
    # 解析并验证JWT的签名和核心声明
    decoded_jwt = jwt.decode(
        jwt_token,
        public_key,
        algorithms=["RS256"],
        issuer=f"https://cognito-idp.us-east-2.amazonaws.com/{user_pool_id}",
        audience="434nnnmg1kfvo0fm4umg3v8bud"
    )
    return decoded_jwt

注意事项

  1. 公钥获取:Cognito会为每个用户池提供固定的JWKS公钥地址,需根据JWT头部的kid匹配对应公钥,确保签名验证正确。
  2. 声明验证:解析时必须验证iss(发行者)和aud(受众),防止伪造的JWT被解析。
  3. 依赖准备:确保Lambda部署包或层包含pyjwt、cryptography、requests三个依赖包。

内容的提问来源于stack exchange,提问作者ZCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:44:55