ecdsa.com
jose (JavaScript)JWT libraries

Error message

signature verification failed

jose (JavaScript) — JWSSignatureVerificationFailed, code ERR_JWS_SIGNATURE_VERIFICATION_FAILED

What it means

jose parsed the JWS successfully and ran the cryptographic check, but the signature does not verify against the key it selected. Structure, algorithm and key type were all acceptable — the mathematics simply did not match, which points at the key or at altered signed bytes.

Why it happens

How to fix it

  1. 1.

    Resolve keys by kid from the issuer's JWKS

    Let jose pick the right key per token instead of pinning one manually; createRemoteJWKSet caches and refreshes keys across rotations.

    js
    import { createRemoteJWKSet, jwtVerify } from "jose";
    
    const jwks = createRemoteJWKSet(new URL("https://issuer.example/.well-known/jwks.json"));
    const { payload } = await jwtVerify(token, jwks, {
      algorithms: ["ES256"],
      issuer: "https://issuer.example",
    });
  2. 2.

    If you sign with node:crypto, emit raw r‖s

    For custom signers, request IEEE P1363 output so the signature is the 64-byte format JWS requires — or verify what your signer produced by checking the third segment's length.

    js
    import { sign } from "node:crypto";
    
    const sig = sign("sha256", Buffer.from(signingInput), {
      key: privateKey,
      dsaEncoding: "ieee-p1363", // raw r||s, 64 bytes for P-256
    });
  3. 3.

    Check the signature segment's shape

    Decode the token's third segment: 64 bytes means raw r‖s (correct for ES256); ~70 bytes starting with 0x30 means DER. The DER ⇄ raw converter below shows the r and s values and converts between the two formats.

Related errors

← Browse the full signature error database