Desenvolvimento

Decodificador de JWT e verificador de assinatura

Cole um token e você recebe o cabeçalho, a carga útil e cada claim explicado, com os timestamps convertidos em datas de verdade. Se você tiver o segredo ou a chave pública, a verificação da assinatura também roda aqui: o token não é enviado para lugar nenhum.

Três partes, duas delas públicas

Um JWT são três blocos unidos por pontos: cabeçalho, carga útil e assinatura. Os dois primeiros estão em base64url — base64 com - e _ no lugar de + e /, e sem o preenchimento de =, para que o token possa ir dentro de uma URL sem quebrar.

base64url é uma codificação, não criptografia. Qualquer pessoa com o token consegue ler todos os claims dele, inclusive o usuário em cujo navegador ele está guardado. Esse é o mal-entendido mais comum sobre JWT, e ele já deixou à mostra um monte de IDs internos de usuário, endereços de e-mail e papéis de usuário. Se um valor precisa ficar em segredo, ele não entra em um token.

A assinatura é a única parte que precisa de uma chave, e tudo o que ela prova é que o cabeçalho e a carga útil não foram alterados depois de assinados. Ela não diz nada sobre quem está com o token agora. Um JWT roubado é um JWT válido.

O campo alg é uma afirmação, não um fato

O cabeçalho indica o algoritmo que o verificador deveria usar, e o cabeçalho é fornecido por quem enviou o token. Dois ataques clássicos saem direto disso.

alg: none. A especificação inclui um modo "não protegido" com a assinatura vazia. Uma biblioteca que confia no cabeçalho vai aceitar numa boa um token que o atacante escreveu à mão. Todo token que chega com none é marcado acima como sem assinatura, e nenhum verificador de produção deveria permitir isso.

RS256 rebaixado para HS256. Se um servidor está configurado para RS256 e verifica o que o cabeçalho pedir, um atacante pode reassinar o token com HS256 usando a própria chave pública do servidor como segredo do HMAC. A chave pública é pública, então isso não custa nada. A correção, em qualquer biblioteca, é fixar o algoritmo esperado em vez de lê-lo do token.

Como ler os timestamps

exp, nbf e iat são valores NumericDate: segundos desde 1 de janeiro de 1970 UTC. Não milissegundos. Passar Date.now() direto para exp produz um token que expira por volta do ano 56000, que todo verificador aceita e ninguém percebe. A tabela acima sinaliza um valor que parece estar em milissegundos.

exp é quando o token deixa de valer, nbf é quando ele começa a valer e iat é quando ele foi emitido. Os verificadores costumam permitir uma pequena diferença de relógio nas duas direções, normalmente 60 segundos, porque o relógio dos servidores desvia.

Por que não dá para cancelar um token

Um JWT é autocontido de propósito: o servidor confere a assinatura e os timestamps, e não precisa consultar banco de dados nenhum. Esse é todo o argumento de desempenho para usar um. O custo é que deslogar alguém, revogar um papel ou banir uma conta não tem efeito até o token expirar, porque nada é consultado na hora de verificar.

As respostas práticas são todas meios-termos. Uma expiração curta com um refresh token move a consulta para a hora de renovar. Uma lista de jti revogados traz de volta o banco de dados que você estava evitando. Um claim de versão do token comparado com o registro do usuário faz a mesma coisa. Não existe versão disso que mantenha a ausência de estado e ainda consiga revogação instantânea.

Até onde esta ferramenta vai

Ela não busca as chaves do emissor. Um verificador de verdade lê o kid do cabeçalho e puxa a chave correspondente do endpoint JWKS do emissor; esta página não faz nenhuma requisição de rede, então a chave você precisa colar. Copiar um objeto de chave de uma resposta JWKS funciona; se você colar o conjunto inteiro com várias chaves, a ferramenta recusa em vez de chutar qual delas usar.

Tokens criptografados estão fora do escopo. Um JWE tem cinco partes em vez de três e a carga útil é texto cifrado; a ferramenta detecta o formato e avisa, em vez de mostrar ruído.

Verificar uma assinatura não é a mesma coisa que aceitar um token. Nada aqui valida se iss e aud são os valores que a sua aplicação espera, e essas verificações importam: um token perfeitamente válido emitido para outra audiência continua sendo o token errado.

Uma pegadinha com segredos HMAC. Alguns emissores guardam o segredo codificado em base64 e o decodificam antes de assinar. Se o texto que você cola não verifica em lugar nenhum, marque "O segredo está em base64" e tente de novo: os bytes que são hasheados são outros, e só isso já muda o resultado.

Perguntas frequentes

É seguro colar aqui um token de produção?

O token fica no seu navegador: esta página é feita de arquivos estáticos, sem servidor por trás, e tanto a decodificação quanto a verificação da assinatura rodam em JavaScript na sua máquina. A ressalva honesta é que um token que passou pela área de transferência e pelo histórico do navegador já é menos privado do que um que ficou em um cabeçalho HTTP, então prefira um token de teste ou já expirado quando puder escolher.

Dá para decodificar um JWT sem o segredo?

Dá, e qualquer outra pessoa também consegue. O cabeçalho e a carga útil são codificados em base64url, não criptografados. O segredo só é necessário para confirmar que o conteúdo não mudou depois da assinatura.

Por que a verificação da assinatura falha com o segredo certo?

Quase sempre porque os bytes são diferentes. Um segredo guardado em base64 precisa ser decodificado antes de ser hasheado, então marque a caixa de base64. Confira também se não veio junto uma quebra de linha ou um espaço no fim do segredo, e garanta que você está verificando o mesmo token, já que reassinar muda a terceira parte.

Quais algoritmos ele consegue verificar?

HS256, HS384 e HS512 com um segredo compartilhado, e as variantes RS, PS e ES em 256, 384 e 512 com uma chave pública em PEM SPKI ou como JWK. EdDSA não é suportado, porque os navegadores ainda não oferecem esse algoritmo pela API Web Crypto em todo lugar.

O que "expirado" significa aqui?

Que o claim exp está no passado de acordo com o relógio do seu próprio dispositivo. Um servidor ainda pode rejeitar um token que o seu relógio considera novo, ou aceitar um que expirou há um minuto, já que a maioria dos verificadores permite uma pequena diferença de relógio.

Última atualização 19 de setembro de 2026