ecdsa.com
PyJWT (Python)JWT libraries

Error message

Signature verification failed

PyJWT (Python) — jwt.exceptions.InvalidSignatureError

What it means

PyJWT decoded the token's structure and ran the signature check, which failed: the signature does not match the key and payload. InvalidSignatureError subclasses DecodeError, so an over-broad except DecodeError can mislabel this as a parsing problem — it is a key/content mismatch. For ES256 tokens there is one extra subtlety: the JWS signature must be the raw 64-byte r‖s form, so tokens minted by hand-rolled signers that emitted ASN.1 DER fail here even when the key is right.

Why it happens

How to fix it

  1. 1.

    Normalize the key and confirm its identity

    Restore real newlines if the PEM came through an environment variable, and print the first line plus a fingerprint so both sides can compare keys.

    python
    import os
    
    pem = os.environ["JWT_PUBLIC_KEY"].replace("\\n", "\n").encode()
    print(pem.splitlines()[0])  # b'-----BEGIN PUBLIC KEY-----'
    
    import jwt
    payload = jwt.decode(token, pem, algorithms=["ES256"])
  2. 2.

    Check kid before assuming corruption

    Read the unverified header and make sure you are verifying with the key the token names. With multiple issuer keys, resolve by kid via 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")

Related errors

← Browse the full signature error database