Error message
jwt signature is required
jsonwebtoken (Node.js) — JsonWebTokenError from jwt.verify()
What it means
The token's third segment is empty — it is an unsecured JWT (`alg: "none"`) or a signed token whose signature was cut off — but you called `verify()` with a key, so a signature is mandatory. jsonwebtoken refuses rather than accept claims nobody signed. If such tokens reach your API from outside, someone may be probing for the classic "alg none" weakness.
Why it happens
An unsecured token with alg "none"
commonRFC 7519 allows unsigned JWTs for contexts where integrity is guaranteed otherwise; an API never is such a context. A token like `eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiJ9.` claims any identity it likes.
Hand-built tokens in tests or tools
occasionalFixtures assembled by base64-encoding a header and payload, or tokens produced by debugging tools with signing switched off, have an empty signature.
The signature was stripped in transit
occasionalA log redactor, a URL length limit or a storage column that cut the token right after the second dot leaves a valid-looking header and payload with nothing to verify.
How to fix it
- 1.
Keep the rejection and the algorithm allow-list
Verify with an explicit `algorithms` list that names only what your issuer uses. Log the request source if unsigned tokens arrive from the outside; do not add a code path that accepts them.
js // Always pass an explicit allow-list; "none" must never be in it. const claims = jwt.verify(token, publicKey, { algorithms: ["ES256"] }); - 2.
Sign test tokens with a throwaway key
Generate a key pair in the test setup and sign fixtures with it, so tests exercise the same verification path as production.
js import { generateKeyPairSync } from "node:crypto"; // Test setup: a throwaway key pair, real signatures, same verification path as production. const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "P-256" }); const token = jwt.sign({ sub: "test-user" }, privateKey, { algorithm: "ES256", expiresIn: "5m" });