Aller au contenu
ecdsa.com
Node.js

jsonwebtoken (Node.js)

jsonwebtoken d’Auth0, le paquet JWT le plus installé pour Node.js : des jetons HMAC, RSA et ECDSA reposant sur node:crypto, avec des contrôles d’algorithme liés au type de clé depuis la version 9, mais sans EdDSA.
Licence
MIT
Version vérifiée
9.0.3 ·
Code source
github.com/auth0/node-jsonwebtoken
Documentation
github.com/auth0/node-jsonwebtoken#readme

Compatibilité en un coup d’œil

JOSE et JWT

Algorithmes JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

jsonwebtoken signe et vérifie des JSON Web Tokens avec trois appels : jwt.sign(), jwt.verify() et jwt.decode(). Il gère la couche JWS au moyen des paquets jws et jwa et confie la cryptographie à node:crypto, si bien que les clés peuvent être des chaînes PEM, des buffers ou des instances KeyObject. jwt.decode() ne fait qu’analyser le jeton : cette fonction ne vérifie jamais la signature, et le code qui en lit les claims se fie à tout ce que l’expéditeur y a écrit.

La version 9 a fermé les voies classiques de confusion d’algorithme, et les essais l’ont confirmé pour la 9.0.3 : sans option algorithms, la liste autorisée découle du type de clé, un jeton HS256 dont la clé est le texte d’une clé publique est refusé, et alg: none ne passe que si vous listez none et ne fournissez aucune clé. Passez tout de même algorithms : l’option documente le contrat et continue de fonctionner si le type de clé change un jour.

La liste des algorithmes s’arrête à l’ensemble de la RFC 7518 : il n’y a ni EdDSA, ni Ed25519, ni ES256K. Un jeton d’un émetteur qui signe en Ed25519 (courant avec jose et dans les écosystèmes Go et Rust) ne peut pas être vérifié ici ; utilisez plutôt jose. ES256 exige aussi une clé P-256, et signer avec une clé P-384 sous ce nom lève une exception au lieu de produire un jeton que d’autres bibliothèques rejetteraient.

Les signatures ECDSA contenues dans le jeton sont sous la forme r‖s brute de 64 octets qu’impose JWS. Quand un jeton a été assemblé à la main à partir d’openssl dgst, de SHA256withECDSA de Java ou d’un KMS cloud, sa signature est en DER et la vérification échoue avec "ES256" signatures must be "64" bytes : collez le jeton dans le débogueur JWT pour voir la longueur de la signature, et corrigez-la avec le convertisseur DER ⇄ brut.

Deux valeurs par défaut surprennent beaucoup d’équipes, l’une plus stricte et l’autre plus laxiste qu’elles ne le pensent : clockTolerance vaut zéro, si bien que quelques secondes de dérive d’horloge entre serveurs suffisent déjà à produire jwt expired, et exp est facultatif, de sorte qu’un jeton émis sans ce claim n’expire jamais. Définissez expiresIn à la signature, et maxAge ou une exigence explicite d’exp à la vérification ; vérifiez les secrets HMAC avec le vérificateur de secrets JWT.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/jsonwebtoken/run.sh a exécuté jsonwebtoken (Node.js) 9.0.3 sur Node.js 24.22.0 dans l’image de conteneur node:24.22.0-bookworm-slim le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • Algorithmes JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

    Signature et vérification réussies lors des essais avec HS256/384/512, RS256/384/512, PS256/384/512 et ES256/384/512. EdDSA, Ed25519, Ed448, ES256K et ML-DSA ont été refusés à la signature.

    Relevé par la vérification
    fact jws-algorithms = HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512
    evidence jws-algorithms: ES256K: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: EdDSA: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: Ed25519: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: Ed448: sign throws Error: "algorithm" must be a valid string enum value
    evidence jws-algorithms: ML-DSA-44: sign throws Error: "algorithm" must be a valid string enum value
  • Encodage des signatures ES256

    raw

    Dans le jeton, les signatures ES256 font 64 octets en r‖s brut, comme l’exige la RFC 7518 ; la bibliothèque les convertit à partir du DER que produit node:crypto.

    Relevé par la vérification
    fact jws-ecdsa-encoding = raw
  • Signature DER dans un JWS

    rejected

    Un jeton dont la signature ES256 a été réencodée en DER échoue avec "ES256" signatures must be "64" bytes, saw "72" (le nombre est la longueur du bloc DER).

    Relevé par la vérification
    fact jws-der-signature = rejected
    evidence jws-der-signature: TypeError: "ES256" signatures must be "64" bytes, saw "72"
  • Liste d’algorithmes autorisés

    from-key

    Sans algorithms, la vérification n’autorise que les algorithmes adaptés à la clé : un jeton HS256 a été vérifié avec un secret partagé, un jeton ES256 avec une clé publique EC, et un jeton RS256 présenté à une clé EC a échoué avec invalid algorithm.

    Relevé par la vérification
    fact jwt-algorithm-allowlist = from-key
    evidence jwt-algorithm-allowlist: RS256 token against an EC key: JsonWebTokenError: invalid algorithm
  • Jetons non signés (alg none)

    opt-in

    Un jeton non signé est refusé avec jwt signature is required dès qu’une clé est fournie ; il n’est vérifié que si algorithms contient none et que l’argument de clé est vide.

    Relevé par la vérification
    fact jwt-alg-none = opt-in
    evidence jwt-alg-none: with a key: JsonWebTokenError: jwt signature is required
    evidence jwt-alg-none: algorithms ["none"] and no key: verified
  • Clé publique utilisée comme secret HMAC

    rejected

    Un jeton HS256 dont la clé HMAC est le texte PEM de la clé publique a été refusé aussi bien sans liste d’algorithmes (invalid algorithm) qu’avec algorithms: ["HS256"] (secretOrPublicKey must be a symmetric key when using HS256).

    Relevé par la vérification
    fact jwt-hmac-public-key = rejected
    evidence jwt-hmac-public-key: no list: JsonWebTokenError: invalid algorithm
    evidence jwt-hmac-public-key: algorithms ["HS256"]: JsonWebTokenError: secretOrPublicKey must be a symmetric key when using HS256
  • Courbe vérifiée par rapport à alg

    enforced

    Signer en ES256 avec une clé P-384 lève "alg" parameter "ES256" requires curve "prime256v1". – ES256, ES384 et ES512 sont liés à P-256, P-384 et P-521.

    Relevé par la vérification
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: Error: "alg" parameter "ES256" requires curve "prime256v1".
  • Décalage d’horloge toléré par défaut

    0s

    Aucune marge de tolérance par défaut : un jeton expiré depuis trois secondes a été rejeté. Définissez clockTolerance, en secondes, pour tolérer une dérive d’horloge.

    Relevé par la vérification
    fact jwt-clock-skew = 0s
  • Claim d’expiration obligatoire

    no

    Un jeton sans claim exp a été vérifié avec succès ; l’expiration n’est contrôlée que si le claim est présent ou si maxAge est défini.

    Relevé par la vérification
    fact jwt-exp-required = no

Utilisation

Émettre et vérifier un jeton ES256 en fixant l’algorithme, l’émetteur et l’audience côté vérification.
import { generateKeyPairSync } from "node:crypto";
import jwt from "jsonwebtoken";

const { privateKey, publicKey } = generateKeyPairSync("ec", { namedCurve: "P-256" });

const token = jwt.sign({ sub: "user-42" }, privateKey, {
  algorithm: "ES256",
  expiresIn: "10m",
  issuer: "https://auth.example.com",
  audience: "api",
});

// Pin the algorithm, issuer and audience instead of trusting the token header.
const claims = jwt.verify(token, publicKey, {
  algorithms: ["ES256"],
  issuer: "https://auth.example.com",
  audience: "api",
});

console.log("sub:", claims.sub);

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur node:24.22.0-bookworm-slim, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
npm init -y >/dev/null && npm install --no-audit --no-fund jsonwebtoken@9.0.3
Commande
node usage.mjs
La sortie doit correspondre à cette expression régulière
sub: user-42

Bibliothèques