Mensagem de erro
secretOrPublicKey must be an asymmetric key when using ES256
O que significa
Você pediu ao jsonwebtoken para verificar (ou assinar — a mensagem irmã diz secretOrPrivateKey) um token ES256, mas o material de chave que você forneceu é um segredo simétrico — uma string comum ou um Buffer que não é PEM/KeyObject. ES256 é ECDSA na P-256: precisa de um par de chaves EC, não de um segredo compartilhado.
Por que acontece
Um segredo da época do HMAC esquecido na configuração
comumO serviço usava HS256 com um segredo compartilhado, alguém trocou o alg para ES256, e JWT_SECRET ainda guarda “supersecret”. Uma string aleatória não é uma chave EC, e o jsonwebtoken se recusa a fingir que é.
O código lê a variável de configuração errada
comumO PEM existe, mas o código lê uma variável que guarda outra coisa — um ID de chave ou uma URL de JWKS (a URL https://issuer/.well-known/jwks.json é uma string, não uma chave). Uma variável vazia é relatada de outro jeito, como “secret or public key must be provided”.
O PEM foi danificado ao passar pela configuração
comumUm PEM que chega com sequências \n literais, entre aspas ou indentado por um arquivo YAML deixa de ser reconhecido como chave, então o jsonwebtoken 9 trata a string como um segredo compartilhado e relata este erro. Restaure as quebras de linha e remova as aspas antes de passá-lo.
JWK passada onde se espera PEM/KeyObject
ocasionalUma JWK é um objeto JSON; convertê-la em string e entregá-la a jwt.verify() produz uma string que não é nem PEM nem KeyObject. Ela precisa ser convertida antes (crypto.createPublicKey({ key: jwk, format: "jwk" })).
Como corrigir
- 1.
Carregar uma chave pública EC de verdade
Verifique ES256 com um PEM (SPKI) ou um KeyObject. Se você tem uma JWK — de um endpoint JWKS, por exemplo —, converta-a antes com node:crypto.
js import { createPublicKey } from "node:crypto"; const key = createPublicKey({ key: jwk, format: "jwk" }); // or a PEM string jwt.verify(token, key, { algorithms: ["ES256"] }); - 2.
Resolver as chaves do JWKS com uma função auxiliar
Se o emissor publica as chaves em uma URL de JWKS, não passe a URL como chave — resolva a chave de cada token pelo kid.
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"] }); - 3.
Ou: você queria mesmo HS256
Se o emissor e o verificador são o seu próprio serviço e o segredo compartilhado é intencional, defina algorithm: "HS256" nos dois lados em vez de ES256. Misturar as duas famílias é justamente o que este erro impede — inclusive o cenário clássico de ataque de confusão de chaves.