Como criar um JWT assinado
- Escolha o Algoritmo. O campo
algem Header (JSON) acompanha a escolha automaticamente. - Edite o Payload (JSON). + iat agora insere o horário atual e + exp em 1 h define a expiração para daqui a uma hora; os dois usam segundos, como a especificação do JWT exige.
- Para HS256, HS384 ou HS512, informe o Segredo e ajuste O segredo está em para Texto, Base64 ou Hex. Para os outros algoritmos, cole uma chave privada ou clique em Gerar par de chaves.
- Clique em Copiar token, ou em Abrir no decodificador para conferi-lo: a aba Decodificar e verificar abre com o token e a chave de verificação já preenchidos.
O exemplo carregado ao abrir é um token HS256 de verdade, assinado com o segredo base64hub-demo-secret, então você pode mudar uma claim e ver a assinatura mudar junto.
Escolher um algoritmo
| Algoritmo | Tipo de chave | Quem pode verificar | Assinatura no token |
|---|---|---|---|
| HS256 | Segredo compartilhado (HMAC-SHA256) | Qualquer um com o mesmo segredo | 43 caracteres |
| RS256, PS256 | Chave privada RSA, 2048 bits ou mais | Qualquer um com a chave pública | 342 caracteres (RSA-2048) |
| ES256 | Chave privada EC em P-256 | Qualquer um com a chave pública | 86 caracteres |
| EdDSA | Chave privada Ed25519 | Qualquer um com a chave pública | 86 caracteres |
HS256 é a escolha mais simples quando um único serviço assina e verifica, como um token de sessão conferido pelo mesmo backend. Quando uma segunda parte precisa verificar, compartilhar um segredo HMAC com ela também permite que ela emita tokens, então mude para um algoritmo assimétrico e publique só a chave pública. ES256 e EdDSA geram tokens bem mais curtos que RSA, o que importa em cookies e headers. PS256 é RSA com o esquema de padding PSS; escolha-o só se todos os verificadores o suportarem.
none está na lista para testar parsers. Um token com alg: none tem assinatura vazia, e qualquer servidor que o aceite pode ser enganado por qualquer pessoa, por isso a ferramenta avisa.
Chaves que este codificador aceita e gera
Para assinar, ele aceita uma chave PEM PKCS#8 (BEGIN PRIVATE KEY), uma RSA PRIVATE KEY PKCS#1, uma EC PRIVATE KEY SEC1 ou um JWK privado. Para criar chaves de teste com o OpenSSL em vez do gerador:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa.pem
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec.pem
openssl genpkey -algorithm ed25519 -out ed.pem
openssl pkey -in ec.pem -pubout -out ec.pub
Gerar par de chaves cria chaves RSA-2048, P-256, P-384, P-521 ou Ed25519 no navegador com WebCrypto, conforme o algoritmo. Você recebe a chave privada em PEM PKCS#8, a chave pública em PEM SPKI e um JWKS cujo kid é o thumbprint RFC 7638 da chave. O JWKS é o que você serviria num jwks_uri para os verificadores baixarem.
No HS256, o segredo é usado como bytes. Se o seu servidor lê o segredo de uma variável de ambiente e o decodifica de Base64 antes, ajuste O segredo está em para Base64 aqui também, senão as assinaturas não vão bater. Um valor do preset de segredo JWT do gerador de chaves Base64 está em Base64URL e decodifica para 32 bytes.
Quais claims colocar no payload
Um access token útil costuma trazer iss (quem emitiu), sub (a quem se refere), aud (para qual API é), iat e um exp curto. Adicione jti se precisar revogar tokens individuais. Os horários são segundos inteiros desde 1970; se você os gera em JavaScript, use Math.floor(Date.now() / 1000), já que Date.now() devolve milissegundos.
O payload é assinado, nunca criptografado. Qualquer um que veja o token consegue decodificá-lo com um decodificador de JWT, então deixe de fora senhas, chaves de API e dados pessoais que você não imprimiria num log.
Assinar um JWT no código
O formato é simples o bastante para montar à mão, o que ajuda ao depurar uma biblioteca. Esta função Node.js gera exatamente o mesmo token que o jwt.encode(payload, secret, algorithm="HS256") do PyJWT para a mesma entrada:
const crypto = require("crypto");
const b64url = (obj) => Buffer.from(JSON.stringify(obj)).toString("base64url");
function signHS256(payload, secret) {
const input = b64url({ alg: "HS256", typ: "JWT" }) + "." + b64url(payload);
const sig = crypto.createHmac("sha256", secret).update(input).digest("base64url");
return input + "." + sig;
}
console.log(signHS256({ sub: "user-42", iat: 1767225600, exp: 1767229200 },
"replace-me-with-32-random-bytes!"));
Ela imprime eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwiaWF0IjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDB9.F3xnXnXW8nUQy-Ay37DF626Lb5lHPKI3IFvqoEf3mTw. Informe o mesmo header, payload e segredo nesta página e você recebe a mesma string. A ferramenta compacta o JSON antes de assinar, então a indentação não importa, mas a ordem das chaves importa, porque a assinatura cobre os bytes exatos. Em produção, use uma biblioteca mantida; veja Base64 em Node.js para o lado da codificação.
Perguntas frequentes
Qual deve ser o tamanho de um segredo HS256?
Pelo menos 256 bits, ou seja, 32 bytes aleatórios. A RFC 7518 exige uma chave no mínimo do tamanho da saída do hash. Um segredo curto, com cara de senha, pode ser quebrado por força bruta offline a partir de um único token, então gere um com o gerador de chaves Base64.
Devo usar HS256 ou RS256?
HS256 quando o mesmo serviço emite e verifica os tokens, porque os dois lados compartilham um segredo. RS256, ES256 ou EdDSA quando outras partes precisam verificar, já que elas recebem só a chave pública e não conseguem emitir tokens.
Por que minha chave privada dá erro?
Chaves protegidas por senha (BEGIN ENCRYPTED PRIVATE KEY) são recusadas. Remova a senha com openssl pkey -in key.pem -out plain.pem e cole o resultado. O tipo de chave também precisa combinar com o algoritmo: uma chave EC não assina RS256.
Como adicionar um kid ao token?
Depois de Gerar par de chaves, copie o kid da saída JWKS e adicione-o ao JSON do header, por exemplo "kid": "…". Quem verifica usa esse valor para escolher a chave certa no conjunto de chaves.