PyJWT кодирует и декодирует токены JSON Web Token с помощью jwt.encode() и jwt.decode(), а ключи подписи получает с эндпоинта JWKS через PyJWKClient. Асимметричные алгоритмы даёт набор опциональных зависимостей crypto, который подтягивает pyca/cryptography; с ним версия 2.15.1 поддерживала семейства HS, RS, PS и ES, ES256K и EdDSA, но не более новые имена Ed25519 и Ed448, для которых выбрасывалось NotImplementedError: Algorithm not supported.
Проверка по умолчанию строгая. jwt.decode() без algorithms завершается ошибкой It is required that you pass in a value for the "algorithms" argument, неподписанный токен с alg: none ни разу не прошёл проверку — даже с algorithms=["none"], — а открытый ключ PEM или OpenSSH, переданный как секрет HS256, отклонён с ошибкой InvalidKeyError. ES256 привязан к P-256: подпись ключом P-384 завершилась ошибкой несовпадения кривой.
Что библиотека оставляет на вас: exp необязателен, поэтому токен без него декодируется бессрочно, если не указать это утверждение в списке require аргумента options, а leeway по умолчанию равен нулю, поэтому серверы, у которых часы расходятся на несколько секунд, уже по-разному определяют, истёк ли срок действия токена. Короткие секреты HMAC принимаются лишь с предупреждением InsecureKeyLengthWarning, которое легко пропустить в логах, — проверьте секрет инструментом проверки секретов JWT.
Подписи ES256 — это 64-байтовый формат raw r‖s, которого требует JWS; токен, подпись которого собрана в DER (например, при подписи через KMS), не проходит проверку с общей ошибкой Signature verification failed. Вставьте токен в отладчик JWT, чтобы увидеть длину подписи, и преобразуйте её в конвертере DER ⇄ raw.
Пример фиксирует алгоритм, издателя и аудиторию, требует exp и допускает расхождение часов в 30 секунд — это четыре настройки, с которыми jwt.decode() можно безопасно вызывать для токенов из другого сервиса.