JWT Tokens Explained: Structure, Security & Decoding

Understand JSON Web Tokens from the inside out. Learn the header, payload, and signature structure, common claims, signing algorithms, and security best practices.

Equipe JSONTechFebruary 1, 202510 min read

O que é um JWT?

Um JSON Web Token (JWT, pronunciado "jot") é uma string compacta e segura para URL que representa claims entre duas partes. É a forma mais comum de lidar com autenticação e autorização em aplicações web modernas.

Quando você entra em uma aplicação web e o servidor devolve um token em vez de criar uma sessão no lado do servidor, há grandes chances de esse token ser um JWT. O navegador o envia em cada requisição seguinte, e o servidor verifica a assinatura sem consultar o banco de dados.

Onde os JWTs são usados

  • Autenticação. Depois que o usuário faz login, o servidor emite um JWT. O cliente armazena e envia no cabeçalho Authorization em cada requisição.
  • Single Sign-On (SSO). JWTs permitem que o usuário se autentique uma vez e acesse vários serviços. Provedores de identidade como Auth0, Okta e Keycloak emitem JWTs que serviços downstream podem verificar de forma independente.
  • Autorização de API. Microsserviços passam JWTs uns aos outros para provar que uma requisição foi feita em nome de um usuário autenticado com permissões específicas.
  • Troca de informações. Como os JWTs são assinados, podem transportar dados confiáveis entre partes sem uma etapa adicional de verificação.

As três partes de um JWT

Todo JWT consiste em três partes codificadas em Base64URL separadas por pontos:

header.payload.signature

Aqui está um JWT real (encurtado para facilitar a leitura):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Vamos decodificar cada parte.

Parte 1: Cabeçalho

O cabeçalho descreve o tipo do token e o algoritmo de assinatura. Decodificado de Base64URL:

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

Parte 2: Payload (claims)

O payload contém as claims — os dados reais que o token carrega. Decodificado:

{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }

O payload é codificado em Base64URL, não criptografado. Qualquer pessoa com o token pode decodificar e ler o payload. Nunca coloque segredos, senhas ou dados pessoais sensíveis no payload de um JWT.

Parte 3: Assinatura

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Experimente você mesmo: cole qualquer JWT no nosso Decodificador de JWT para inspecionar as três partes na hora.

Claims comuns em JWT

ClaimNome completoDescrição
subSubjectSobre quem é o token (em geral um ID de usuário)
issIssuerQuem emitiu o token
audAudienceDestinatário pretendido
expExpiration TimeTimestamp Unix após o qual o token é inválido
iatIssued AtTimestamp Unix em que o token foi criado
nbfNot BeforeO token é inválido antes deste timestamp
jtiJWT IDIdentificador único para evitar reutilização do token

Algoritmos de assinatura comparados

AlgoritmoTipoChaveMelhor para
HS256Simétrico (HMAC)Um único segredo compartilhadoConfigurações simples
RS256Assimétrico (RSA)Par de chaves privada/públicaSistemas distribuídos, SSO
ES256Assimétrico (ECDSA)Par de chaves privada/públicaIgual ao RS256, com chaves menores

Boas práticas de segurança

  • Nunca armazene segredos no payload. Use JWE para tokens criptografados.
  • Use tempos de expiração curtos. 5 a 15 minutos.
  • Sempre use HTTPS.
  • Valide todas as claims. Verifique exp, iss, aud.
  • Não aceite alg: none.
  • Use uma lista permitida de algoritmos.
  • Armazene tokens com segurança. Cookies HttpOnly em vez de localStorage.

Erros comuns com JWT

  • Colocar o JWT na URL.
  • Não validar a assinatura.
  • Segredo fraco para HS256.
  • Tokens que nunca expiram.
  • Armazenar dados demais.

Fluxo de renovação de token

  1. O usuário faz login. O servidor devolve access token (curta duração) e refresh token (longa duração).
  2. O cliente envia o access token em cada requisição.
  3. O access token expira; a API retorna 401.
  4. O cliente envia o refresh token para /refresh.
  5. O servidor emite novos tokens (rotação do refresh token).
  6. O cliente tenta de novo com o novo access token.
// Simplified refresh flow (client-side)
const handleApiRequest = async (url, options) => {
  let response = await fetch(url, {
    ...options,
    headers: { ...options.headers, Authorization: `Bearer ${getAccessToken()}` },
  });
  if (response.status === 401) {
    const refreshResponse = await fetch("/api/refresh", {
      method: "POST",
      body: JSON.stringify({ refresh_token: getRefreshToken() }),
    });
    if (refreshResponse.ok) {
      const { access_token, refresh_token } = await refreshResponse.json();
      saveTokens(access_token, refresh_token);
      response = await fetch(url, {
        ...options,
        headers: { ...options.headers, Authorization: `Bearer ${access_token}` },
      });
    } else { redirectToLogin(); }
  }
  return response;
};

JWTs versus sessões: quando usar cada um

AspectoJWTSessões no servidor
Armazenamento de estadoCliente (sem estado)Servidor (armazenamento de sessão)
EscalabilidadeFácilExige armazenamento compartilhado
RevogaçãoDifícilFácil
Tamanho do payloadMaiorMenor
Cross-domainFunciona bemExige configuração de CORS
MicrosserviçosIdealCada serviço consulta o armazenamento
SimplicidadeMais complexoMais simples

Use JWTs para serviços distribuídos, apps mobile e consumidores de API de terceiros. Use sessões para revogação simples, apps monolíticos e a opção segura mais direta.

Experimente você mesmo: decodifique e inspecione qualquer JWT na hora com o nosso Decodificador de JWT — nenhum dado sai do seu navegador.

Ferramentas relacionadas