auth0/node-jsonwebtoken
The user-facing surface is three functions, each with a dual sync/async calling convention selected by whether a trailing callback is supplied. `sign` turns a payload plus key into a compact JWS, mapping option names onto registered claim names and computing time-based claims. `verify` is the security-critical path: it re-decodes, resolves a key (possibly via an async key-lookup callback for JWKS/kid workflows), enforces an algorithm allow-list, checks key/alg compatibility, verifies the signature, then runs seven independent claim checks. `decode` is the deliberately unauthenticated escape hatch. Twelve signing algorithms plus `none` are supported, and a set of explicit backwards-compatibility escape valves (`allowInsecureKeySizes`, `allowInvalidAsymmetricKeyTypes`) let callers opt out of the newer hardening.
- `jwt.sign(payload, secretOrPrivateKey, [options, callback])` supports thirteen options validated by `sign_options_schema`: `expiresIn`, `notBefore`, `audience`, `algorithm`, `header`, `encoding`, `issuer`, `subject`, `jwtid`, `noTimestamp`, `keyid`, `mutatePayload`, `allowInsecureKeySizes`, `allowInvalidAsymmetricKeyTypes` — and rejects any key not in that schema with `"<key>" is not allowed in "options"`.
- Four sign options are sugar that write registered claims, via the `options_to_payload` table: `audience`→`aud`, `issuer`→`iss`, `subject`→`sub`, `jwtid`→`jti`. Supplying both the option and the raw claim is an error (`Bad "options.<x>" option. The payload already has an "<claim>" property.`).
- Non-object payloads (strings, numbers, Buffers) are supported for signing but reject the seven object-only options listed in `options_for_objects` with `invalid <opts> option for <typeof> payload`; a Buffer payload round-trips as its string form.
- `mutatePayload: false` (the default) shallow-clones the payload with `Object.assign({}, payload)` before adding `iat`/`exp`/`nbf`, which is what makes signing a frozen or sealed payload work.
- `options.encoding` (default `utf8`) is passed through to `jws`, so `{encoding: 'binary'}` produces a differently-encoded payload segment for non-ASCII characters.
- `jwt.verify(token, secretOrPublicKey, [options, callback])` supports thirteen options: `algorithms`, `audience`, `complete`, `issuer`, `jwtid`, `ignoreExpiration`, `ignoreNotBefore`, `subject`, `clockTolerance`, `maxAge`, `clockTimestamp`, `nonce`, `allowInvalidAsymmetricKeyTypes`.
- `secretOrPublicKey` may be a key-lookup function `(header, cb)` — the JWKS/`kid` integration point — but only when a callback is also supplied; otherwise verify fails with `verify must be called asynchronous if secret or public key is provided as a callback`.
- Audience matching accepts a string, a `RegExp`, or an array of either, and matches if ANY token `aud` entry matches ANY expected audience — an any-to-any `some`/`some` cross product.
- `clockTolerance` (seconds of slack) and `clockTimestamp` (override for "now") apply to `nbf`, `exp`, and `maxAge` uniformly; `clockTimestamp` must be a number or verify fails early with `clockTimestamp must be a number`.
- `maxAge` is an independent expiry ceiling computed from `payload.iat`, requires a numeric `iat` (`iat required when maxAge is specified`), and cannot loosen `exp` — a token past `exp` still fails even with `maxAge: '1000y'`.
- `complete: true` on either `verify` or `decode` returns `{header, payload, signature}` instead of the bare payload — this is how callers reach `kid` and `alg` for key selection.
- `jwt.decode(token, options)` performs no signature verification at all, and silently swallows a `JSON.parse` failure on the payload — returning the raw string payload rather than throwing.
- Unsigned (`alg: none`) tokens are supported on both sides but require explicit opt-in on verify: `please specify "none" in "algorithms" to verify unsigned tokens`, and passing a key alongside a signature-less token yields `jwt signature is required`.
- Two named backwards-compatibility escape hatches exist and are documented as discouraged: `allowInsecureKeySizes` (permits RSA modulus < 2048) and `allowInvalidAsymmetricKeyTypes` (skips the `validateAsymmetricKey` gate).