Saltar al contenido
ecdsa.com
PyJWT (Python)Bibliotecas de JWT

Mensaje de error

Signature verification failed

PyJWT (Python) — jwt.exceptions.InvalidSignatureError

Qué significa

PyJWT decodificó la estructura del token y ejecutó la comprobación de la firma, que falló: la firma no corresponde a la clave y la carga útil. InvalidSignatureError es una subclase de DecodeError, así que un except DecodeError demasiado amplio puede etiquetar esto como un problema de análisis cuando en realidad la clave y el contenido no coinciden. Con los tokens ES256 hay una sutileza más: la firma JWS debe tener la forma r‖s en bruto de 64 bytes, así que los tokens generados por firmantes hechos a mano que emitían ASN.1 DER fallan aquí aunque la clave sea la correcta.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Calcular la huella digital de la clave en ambos lados

    Imprime una huella digital SHA-256 de la clave pública que cargó el verificador y compárala con la del emisor. Si difieren, se acabó la búsqueda; si coinciden, el problema está en los bytes del token.

    python
    import hashlib
    from cryptography.hazmat.primitives import serialization
    
    public_key = serialization.load_pem_public_key(pem_bytes)  # the key the verifier uses
    spki = public_key.public_bytes(serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo)
    print(hashlib.sha256(spki).hexdigest())  # compare with the issuer's
  2. 2.

    Comprobar el kid antes de dar por hecho que el token está dañado

    Lee el encabezado sin verificar y asegúrate de que verificas con la clave indicada en el token. Si el emisor tiene varias claves, resuelve la clave por kid mediante PyJWKClient.

    python
    import jwt
    
    header = jwt.get_unverified_header(token)
    print(header)  # {'alg': 'ES256', 'kid': '...'}
    
    from jwt import PyJWKClient
    key = PyJWKClient("https://issuer.example/.well-known/jwks.json") \
        .get_signing_key_from_jwt(token).key
    payload = jwt.decode(token, key, algorithms=["ES256"], audience="api://orders")

Errores relacionados

Explorar toda la base de datos de errores de firma