Decodificador de JWT online

O decodificador de JWT lê um JSON Web Token e mostra o conteúdo do header e do payload, incluindo as datas de emissão e expiração e se o token já expirou. O token é lido no seu navegador e não é enviado a nenhum servidor. A ferramenta não verifica a assinatura: ela só mostra o que está escrito no token.

Atualizado em · Por Leonardo Gaertner

Achou um resultado errado ou tem uma sugestão? Avise por e-mail.

Como usar

  1. Cole o token no campo, com ou sem o prefixo Bearer.
  2. Veja o header (algoritmo e tipo) e o payload (os dados, chamados claims).
  3. Confira as datas de emissão, início de validade e expiração, e o estado do token.

Como funciona

Um JWT tem três partes separadas por ponto: header, payload e assinatura. As duas primeiras são objetos JSON codificados em Base64URL, uma variação do Base64 que troca + e / por - e _ e dispensa o preenchimento com =.

O payload traz claims registrados, como iss (emissor), sub (assunto), aud (destinatário), exp (expiração), nbf (válido a partir de), iat (emitido em) e jti (identificador). As datas são contadas em segundos desde 1970, e a ferramenta as converte para o seu fuso horário.

Decodificar não é o mesmo que verificar. Para confiar em um token, o servidor precisa validar a assinatura com a chave correta. Esta ferramenta não faz isso, e o conteúdo de um JWT assinado não é secreto: qualquer pessoa com o token consegue lê-lo.

Exemplo de header

Parte inicial do token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Decodificada: {"alg":"HS256","typ":"JWT"}

Fonte: RFC 7519: JSON Web Token (JWT)

Em código

Decodificar um JWT em código é só ler o header e o payload em Base64URL. Isso não prova que o token é confiável: para isso, verifique a assinatura.

JavaScript
function decodificarJWT(token) {
  const [header, payload] = token.split('.');

  const decodificar = (parte) => {
    // Base64URL usa - e _ no lugar de + e /, e não tem o preenchimento com =
    const base64 = parte.replace(/-/g, '+').replace(/_/g, '/');
    const binario = atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '='));
    const bytes = Uint8Array.from(binario, (c) => c.charCodeAt(0));
    return JSON.parse(new TextDecoder().decode(bytes));
  };

  return { header: decodificar(header), payload: decodificar(payload) };
}

Só lê o conteúdo. Não verifica a assinatura.

JavaScript
import { createHmac, timingSafeEqual } from 'node:crypto';

function verificarHS256(token, segredo) {
  const [header, payload, assinatura] = token.split('.');

  // Aceite só o algoritmo que você espera, nunca o que o token diz
  const cabecalho = JSON.parse(Buffer.from(header, 'base64url').toString());
  if (cabecalho.alg !== 'HS256') throw new Error('Algoritmo não aceito');

  const esperada = createHmac('sha256', segredo).update(`${header}.${payload}`).digest();
  const recebida = Buffer.from(assinatura, 'base64url');
  if (recebida.length !== esperada.length || !timingSafeEqual(recebida, esperada)) {
    throw new Error('Assinatura inválida');
  }

  const dados = JSON.parse(Buffer.from(payload, 'base64url').toString());
  if (dados.exp && dados.exp * 1000 <= Date.now()) throw new Error('Token expirado');
  return dados;
}

Verifica a assinatura HS256, recusa o algoritmo none e confere a expiração.

Python
import base64
import hashlib
import hmac
import json
import time


def base64url(parte: str) -> bytes:
    return base64.urlsafe_b64decode(parte + "=" * (-len(parte) % 4))


def verificar_hs256(token: str, segredo: str) -> dict:
    header, payload, assinatura = token.split(".")

    # Aceite só o algoritmo que você espera, nunca o que o token diz
    if json.loads(base64url(header)).get("alg") != "HS256":
        raise ValueError("Algoritmo não aceito")

    esperada = hmac.new(segredo.encode(), f"{header}.{payload}".encode(), hashlib.sha256).digest()
    if not hmac.compare_digest(esperada, base64url(assinatura)):
        raise ValueError("Assinatura inválida")

    dados = json.loads(base64url(payload))
    if "exp" in dados and dados["exp"] <= time.time():
        raise ValueError("Token expirado")
    return dados

A mesma verificação em Python.

Perguntas frequentes

O JWT é criptografado?

Em geral, não. O JWT mais comum é apenas assinado (JWS): o conteúdo é legível por qualquer pessoa, e a assinatura só garante que ele não foi alterado. Por isso não se deve colocar senhas ou dados sigilosos no payload.

Esta ferramenta verifica se o token é autêntico?

Não. Ela só decodifica e exibe o conteúdo. A verificação da assinatura exige a chave do emissor e deve ser feita no servidor da sua aplicação.

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

O token é processado no seu navegador e não é enviado ao PraDev. Ainda assim, um token válido funciona como uma senha temporária. Prefira usar tokens de teste ou já expirados, e nunca compartilhe um token ativo.

Como sei se o token expirou?

Pelo claim exp, a data de expiração em segundos desde 1970. A ferramenta compara esse valor com a hora do seu computador e informa se o token está válido ou expirado.