Pular para o conteúdo
ecdsa.com
Node.js

jsonwebtoken (Node.js)

O jsonwebtoken, da Auth0, o pacote JWT mais instalado para Node.js: tokens HMAC, RSA e ECDSA sobre o node:crypto, com verificações de algoritmo vinculadas ao tipo da chave desde a versão 9 — mas sem EdDSA.
Licença
MIT
Versão verificada
9.0.3 ·
Código-fonte
github.com/auth0/node-jsonwebtoken
Documentação
github.com/auth0/node-jsonwebtoken#readme

Visão geral da compatibilidade

JOSE e JWT

Algoritmos JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

O jsonwebtoken assina e verifica JSON Web Tokens com três chamadas: jwt.sign(), jwt.verify() e jwt.decode(). Ele trata a camada JWS por meio dos pacotes jws e jwa e faz a criptografia com o node:crypto; por isso, as chaves podem ser strings PEM, buffers ou instâncias de KeyObject. jwt.decode() apenas analisa o token — nunca verifica a assinatura, e o código que lê claims a partir dele confia em tudo o que o remetente escreveu.

A versão 9 fechou os caminhos clássicos de confusão de algoritmo, e o teste confirmou isso na 9.0.3: sem a opção algorithms, a lista de algoritmos permitidos vem do tipo da chave, um token HS256 que usa como chave o texto de uma chave pública é recusado, e alg: none só passa quando você lista none e não fornece chave nenhuma. Passe algorithms mesmo assim — isso documenta o contrato e continua funcionando se o tipo da chave mudar algum dia.

A lista de algoritmos para no conjunto da RFC 7518: não há EdDSA, Ed25519 nem ES256K. Um token de um emissor que assina com Ed25519 — comum em ambientes com jose, Go e Rust — não pode ser verificado aqui; use o jose em vez disso. O ES256 também exige uma chave P-256, e assinar com uma chave P-384 sob esse nome lança uma exceção, em vez de produzir um token que outras bibliotecas rejeitariam.

As assinaturas ECDSA dentro do token estão na forma r‖s bruta de 64 bytes que o JWS exige. Quando um token é montado à mão a partir do openssl dgst, do SHA256withECDSA do Java ou de um KMS de nuvem, a assinatura dele está em DER, e a verificação falha com "ES256" signatures must be "64" bytes — cole o token no depurador de JWT para ver o tamanho da assinatura e corrija-a com o conversor DER ⇄ bruto.

Dois padrões surpreendem muitas equipes, um mais rígido e outro mais permissivo do que elas supõem: clockTolerance é zero, então alguns segundos de diferença de relógio entre servidores já resultam em jwt expired, e exp é opcional, então um token emitido sem ela nunca expira. Defina expiresIn ao assinar e maxAge ou uma exigência explícita de exp ao verificar; confira segredos HMAC com o verificador de segredos JWT.

Os fatos e as verificações por trás deles

Nada abaixo foi copiado da documentação. A verificação content/libraries/verify/jsonwebtoken/run.sh executou jsonwebtoken (Node.js) 9.0.3 em Node.js 24.22.0 na imagem de contêiner node:24.22.0-bookworm-slim em 20 de outubro de 2026; a página precisa corresponder ao que a verificação imprimiu, e cada fato lista essas linhas.

  • Algoritmos JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512

    No teste, assinatura e verificação funcionaram com HS256/384/512, RS256/384/512, PS256/384/512 e ES256/384/512. EdDSA, Ed25519, Ed448, ES256K e ML-DSA foram recusados na assinatura.

    Registrado pela verificação
    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
  • Codificação da assinatura ES256

    raw

    As assinaturas ES256 no token são 64 bytes de r‖s brutos, como exige a RFC 7518; a biblioteca converte a partir do DER que o node:crypto produz.

    Registrado pela verificação
    fact jws-ecdsa-encoding = raw
  • Assinatura DER dentro de um JWS

    rejected

    Um token cuja assinatura ES256 foi recodificada em DER falha com "ES256" signatures must be "64" bytes, saw "72" (o número é o tamanho do blob DER).

    Registrado pela verificação
    fact jws-der-signature = rejected
    evidence jws-der-signature: TypeError: "ES256" signatures must be "64" bytes, saw "72"
  • Lista de algoritmos permitidos

    from-key

    Sem algorithms, a verificação só permite os algoritmos compatíveis com a chave: um token HS256 foi verificado com um segredo compartilhado e um token ES256 com uma chave pública EC, e um token RS256 verificado com uma chave EC falhou com invalid algorithm.

    Registrado pela verificação
    fact jwt-algorithm-allowlist = from-key
    evidence jwt-algorithm-allowlist: RS256 token against an EC key: JsonWebTokenError: invalid algorithm
  • Tokens sem assinatura (alg none)

    opt-in

    Um token sem assinatura é recusado com jwt signature is required sempre que uma chave é fornecida; ele só é verificado quando algorithms contém none e o argumento da chave está vazio.

    Registrado pela verificação
    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
  • Chave pública usada como segredo HMAC

    rejected

    Um token HS256 cuja chave HMAC é o texto PEM da chave pública foi recusado tanto sem lista de algoritmos (invalid algorithm) quanto com algorithms: ["HS256"] (secretOrPublicKey must be a symmetric key when using HS256).

    Registrado pela verificação
    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
  • Curva conferida com o alg

    enforced

    Assinar ES256 com uma chave P-384 lança "alg" parameter "ES256" requires curve "prime256v1". — ES256, ES384 e ES512 estão vinculados a P-256, P-384 e P-521.

    Registrado pela verificação
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: Error: "alg" parameter "ES256" requires curve "prime256v1".
  • Tolerância padrão de diferença de relógio

    0s

    Sem tolerância por padrão: um token que tinha expirado três segundos antes foi rejeitado. Defina clockTolerance, em segundos, para compensar a diferença de relógio.

    Registrado pela verificação
    fact jwt-clock-skew = 0s
  • Claim de expiração obrigatória

    no

    Um token sem a claim exp foi verificado com sucesso; a expiração só é aplicada quando a claim está presente ou maxAge está definido.

    Registrado pela verificação
    fact jwt-exp-required = no

Uso

Emita e verifique um token ES256, com fixação do algoritmo, do emissor e do público-alvo no lado da verificação.
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);

O executor de trechos de código roda cada exemplo literalmente na imagem de contêiner node:24.22.0-bookworm-slim, e a execução falha se a saída não corresponder.

Configuração
npm init -y >/dev/null && npm install --no-audit --no-fund jsonwebtoken@9.0.3
Comando
node usage.mjs
A saída deve corresponder a (expressão regular)
sub: user-42

Bibliotecas