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

Posted

技术标签:

【中文标题】在 Python 中使用来自 Gravitee 的公钥解码 JWT 令牌时出现问题【英文标题】:Problem decoding JWT token with public key from Gravitee in Python 【发布时间】:2022-01-08 06:24:51 【问题描述】:

我正在尝试使用公钥解码 Gravitee JWT 令牌。我已经测试了 PyJWT、authlib、python-jose 和 jwcrypto 库,并查看了此页面上的很多帖子,但我在所有帖子中都遇到了相同的错误,我无法解决问题。

错误:

('无法反序列化密钥数据。数据可能格式不正确,可能使用不受支持的算法加密,或者可能是不受支持的密钥类型(例如具有显式参数的 EC 曲线)。' , [_OpenSSLErrorWithText(code=151584876, lib=9, reason=108, reason_text=b'error:0909006C:PEM routines:get_name:no start line')])

首先我按照 Gravitee 的说明获得了公钥:

https://docs.gravitee.io/am/current/am_userguide_create_certificate.html

来自https://jwt.io 的关于我的令牌的一些信息:

HEADER:ALGORITHM & TOKEN TYPE


  "kid": "default",
  "alg": "RS256"

Python 软件包版本:

PyJWT==2.3.0(也用 2.1.0 测试过)

cryptography==36.0.0(一些帖子建议是必需的)

我的代码:

from rest_framework import permissions
from rest_framework.exceptions import APIException
from django.conf import settings
import jwt


class TokenNotValid(APIException):
    status_code = 403
    default_detail = "Invalid or absent JWT token field."


class NoAuthHeader(APIException):
    status_code = 403
    default_detail = "Absent 'Authorization' header."


class ValidJWTPermission(permissions.BasePermission):
    """
    Global permission check for JWT token.
    """

    def _get_pubkey(self):
        key = """-----BEGIN PUBLIC KEY-----\n""" + settings.GRAVITEE_PUBLIC_KEY + """\n-----END PUBLIC KEY-----"""
        return key

    def has_permission(self, request, view):

        auth_header = request.META.get('HTTP_AUTHORIZATION')
        # print("Received header:")
        # print(auth_header)
        if auth_header is None:
            raise NoAuthHeader

        try:
            token = auth_header.split()[1]
            # print("Encoded Token:")
            # print(token)
            public_key = self._get_pubkey()
            print(public_key)

            claims = jwt.decode(token, key=public_key, algorithms=['RS256'])
            claims.validate()
        except Exception as e:
            print(e)
            raise TokenNotValid

        # print("Decoded token:")
        # print(dec_token)

        return True

我还测试了像 key.encode()key.encode('ascii') 这样的密钥编码,或者用“BEGIN RSA PUBLIC KEY”而不是“BEGIN PUBLIC KEY”组合密钥,任何东西都适合我。我总是有同样的错误。

【问题讨论】:

【参考方案1】:

根据库的不同,您通常需要 JWK 格式的密钥,如以下链接所示: https://demo.identityserver.io/.well-known/openid-configuration/jwks

JSON Web Key (JWK) format 是处理令牌时表示键的标准,也许您的库也希望采用这种格式?

【讨论】:

感谢您的回复。图书馆想要 PEM 并且不支持 JWK 格式,我尝试了很多密钥格式的可能性,但它们中的任何一个都有效。 您是否使用 openssl 验证过您实际上可以读取密钥并且它是有效的?比如使用“openssl rsa -text -noout -pubin -in rsa-public-key.pem”

以上是关于在 Python 中使用来自 Gravitee 的公钥解码 JWT 令牌时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

Gravitee.io api gateway 试用

Gravitee.io docker-compose运行

sh gravitee conf

如何在 Python 3 中使用来自 Python 2 的 .so 模块?

在python中使用来自textinput的值

无法在另一个 python 脚本中使用来自 python 函数的属性