O python-jose implementa JWS, JWE, JWK e JWT com backends intercambiáveis — o ecdsa em Python puro, o pycryptodome ou o cryptography; o teste instalou o extra cryptography. Anos de tutoriais de FastAPI e Flask o tornaram muito difundido, mas o desenvolvimento é lento: a 3.4.0 (fevereiro de 2025) saiu quase quatro anos depois da 3.3.0, e projetos novos costumam escolher o PyJWT, o jwcrypto ou o joserfc.
Em jwt.decode(), algorithms é opcional e, sem ele, o algoritmo vem do cabeçalho do token. Somado ao alerta GHSA-3qf3-8w2g-rqmx (CVE-2026-85394), publicado em setembro de 2026 e sem correção na 3.5.0, isso é explorável: a proteção contra o uso de chaves públicas como segredos HMAC reconhece texto PEM e OpenSSH, mas não a mesma chave como bytes DER. O teste reproduziu o problema — um token HS256 cuja chave HMAC era a chave pública DER foi verificado com essa chave quando algorithms foi omitido e foi rejeitado com The specified alg value is not allowed assim que se passou algorithms=["ES256"]. Sempre passe algorithms, mantenha as chaves públicas como strings PEM e verifique segredos com o verificador de segredos JWT.
O conjunto de algoritmos é o mais antigo entre as bibliotecas Python: apenas as famílias HS, RS e ES. PS256, EdDSA e ES256K lançam Algorithm … not supported., então tokens de provedores que migraram para Ed25519 ou RSA-PSS não podem ser verificados. O ES256 também não está vinculado à P-256: uma chave P-384 produziu, sob um cabeçalho ES256, uma assinatura de 96 bytes que o python-jose verificou, mas que outras bibliotecas, como o jose e o PyJWT, recusam.
As assinaturas ES256 são 64 bytes de r‖s brutos, e uma assinatura DER falha com Signature verification failed.; o depurador de JWT mostra qual forma um token traz. exp é opcional e a tolerância é zero, a menos que você defina require_exp e leeway em options, como faz o exemplo.
Tokens sem assinatura foram rejeitados com Unable to find an algorithm for key, mesmo com algorithms=["none"].