O PyJWT codifica e decodifica JSON Web Tokens com jwt.encode() e jwt.decode() e busca chaves de assinatura em um endpoint JWKS com PyJWKClient. Os algoritmos assimétricos vêm do extra crypto, que instala o pyca/cryptography; com ele, a 2.15.1 tratou as famílias HS, RS, PS e ES, o ES256K e o EdDSA, mas não os nomes mais novos Ed25519 e Ed448, que lançaram NotImplementedError: Algorithm not supported.
Seus padrões de verificação são estritos. jwt.decode() sem algorithms falha com It is required that you pass in a value for the "algorithms" argument, um token alg: none sem assinatura nunca passou na verificação — nem mesmo com algorithms=["none"] — e uma chave pública PEM ou OpenSSH usada como segredo HS256 foi recusada com InvalidKeyError. O ES256 está vinculado à P-256: assinar com uma chave P-384 falhou com um erro de curva incompatível.
O que fica por sua conta: exp é opcional, então um token sem ela é decodificado para sempre, a menos que você a inclua em require no argumento options, e leeway é zero por padrão, então servidores com poucos segundos de diferença de relógio já discordam sobre a expiração. Segredos HMAC curtos são aceitos apenas com um InsecureKeyLengthWarning, fácil de passar despercebido nos logs — teste um segredo com o verificador de segredos JWT.
As assinaturas ES256 estão na forma r‖s bruta de 64 bytes que o JWS exige; um token cuja assinatura foi montada em DER — por exemplo, a partir de uma chamada de assinatura a um KMS — falha com o genérico Signature verification failed. Cole o token no depurador de JWT para ver o tamanho da assinatura e converta com o conversor DER ⇄ bruto.
O exemplo fixa o algoritmo, o emissor e o público-alvo, exige exp e admite 30 segundos de diferença de relógio — as quatro configurações que tornam seguro chamar jwt.decode() com tokens de outro serviço.