Português (Brasil)

O que um JWT decodificado prova

Um decodificador JWT mostra o que um token afirma. Não pode mostrar se essas afirmações são verdadeiras. Este guia aborda o que são os três segmentos, o que a decodificação estabelece e o que não estabelece e os ataques que residem na lacuna entre os dois.

Três segmentos, dois dos quais são apenas JSON

Um JWT em sua forma comum é um JWS: três segmentos base64url separados por pontos. O primeiro é um cabeçalho, o segundo é uma carga útil e o terceiro é uma assinatura.

O cabeçalho e a carga útil são objetos JSON comuns que foram codificados em base64url. Codificado, não criptografado. Qualquer pessoa que possua o token pode ler ambos, instantaneamente, sem chave – isso não é uma falha, é o design. Um JWT é uma declaração assinada, não um envelope lacrado. A assinatura garante que a declaração não foi alterada; não faz nada para mantê-lo privado.

Vale a pena declarar claramente a consequência porque é rotineiramente esquecida: nunca coloque nada confidencial em uma carga útil JWT. Nem uma senha, nem um identificador nacional completo, nem detalhes internos do sistema. Suponha que a carga útil seja pública, porque para qualquer pessoa que possua o token, ela é.

O terceiro segmento é a assinatura, calculada sobre os dois primeiros. É a única parte que carrega algum valor de segurança e é a parte que um decodificador não pode avaliar.

O que a decodificação prova: nada

Este é o ponto de todo o guia. A decodificação de JWT analisa duas strings base64url em JSON. Isso confirma que o token está bem formado. Não confirma que o token seja genuíno, que tenha sido emitido pela parte nomeada na reivindicação “iss”, que as reivindicações não tenham sido editadas ou que alguma vez tenha sido válido.

Qualquer um pode construir um token. Pegue qualquer JWT, altere "role": "user" para "role": "admin", codifique novamente a carga útil, grampeie qualquer assinatura no final e um decodificador exibirá suas declarações editadas com a mesma confiança com que exibiu o original. Não há como saber a diferença, pois verificar a diferença é uma operação diferente que requer uma chave que o decodificador não possui.

Portanto, quando um decodificador – este ou qualquer outro – mostra “exp: 2026-01-01”, o que ele realmente está dizendo é: esse token contém uma declaração de que expira naquela data. Se essa afirmação significa alguma coisa depende inteiramente de a assinatura ser válida, o que não foi verificado.

Esta ferramenta apenas decodifica e diz isso na página, ao lado dos resultados, sempre. Não em uma nota de rodapé. A razão é que um decodificador que não fala sobre isso está treinando seus usuários para ler dados não verificados como se fossem verificados, e esse hábito é a raiz de toda uma família de bugs de autenticação.

Por que esta ferramenta não oferece verificação

A verificação precisa de três coisas que uma página da web não pode ter de forma responsável: a chave do emissor, o algoritmo fixado antecipadamente e uma política sobre o que rejeitar.

A chave é o problema óbvio. Para algoritmos HMAC (HS256 e amigos) a chave é um segredo compartilhado — o mesmo segredo usado para criar tokens. Colá-lo em uma página da web significa colar uma credencial que pode gerar tokens válidos em uma página da web. Para RSA e ECDSA a chave pública não é secreta, mas você ainda precisaria buscar a chave certa no endpoint JWKS correto e confiar que você tinha.

O algoritmo é o problema sutil e a fonte de dois ataques bem conhecidos. A primeira é alg: “none”: o cabeçalho afirma que o token não está assinado e um verificador que respeita o cabeçalho em vez de sua própria configuração aceita qualquer coisa. A segunda é a confusão RS256-to-HS256: o invasor pega uma chave pública – que é, por definição, pública – altera o cabeçalho para dizer HS256 e assina o token usando essa chave pública como o segredo HMAC. Um verificador que lê o algoritmo do token e procura “a chave” irá validá-lo.

Ambos os ataques vêm do mesmo erro: deixar o token dizer ao verificador como verificar o token. Um verificador correto ignora o algoritmo do cabeçalho e usa aquele com o qual foi configurado. Essa é uma decisão que pertence ao sistema que confia no token – não a uma ferramenta conveniente e não a quem colou algo em um formulário.

Por que não colar tokens de produção em qualquer lugar

Um token de acesso é uma credencial de portador. É isso que “portador” significa no cabeçalho da Autorização: quem o carrega é você. Não há um segundo fator e geralmente não há como diferenciar um token roubado de um token legítimo. Até que expire, é uma chave funcional para sua conta.

Portanto, colar um token ativo em qualquer página da web é entregar uma credencial a essa página. Este decodifica tudo localmente e não faz nenhuma solicitação de rede após o carregamento da página – você pode confirmar isso no painel de rede do seu navegador, e deveria, porque leva dez segundos. Mas observe qual é realmente esse argumento: uma afirmação, em um site, de que o site é confiável. Cada site que exfiltra tokens faz exatamente a mesma afirmação, e o visitante não consegue perceber a diferença à primeira vista.

O hábito seguro não depende de julgar os sites corretamente. Use tokens expirados, tokens de ambiente de teste ou tokens que você criou para essa finalidade. Se você já colou um token de produção em algum lugar — em qualquer lugar — gire-o. A revogação é barata; um incidente não é.

O mesmo se aplica com mais força à assinatura de chaves. Não há razão legítima para digitar um segredo HMAC ou uma chave privada em uma página da web, e qualquer site que solicite uma "verificação" do seu token está solicitando a capacidade de falsificar tokens. Essa é a razão concreta pela qual esta ferramenta não possui recurso de verificação: o recurso requer a solicitação.

Lendo as afirmações que importam

RFC 7519 registra um pequeno conjunto de nomes de declarações. "iss" é o emissor, "sub" o assunto sobre o qual o token se trata, "aud" o público-alvo, "exp" a expiração, "nbf" o horário válido mais antigo, "iat" o horário de emissão e "jti" um ID exclusivo para detecção de repetição. Todo o resto é específico do aplicativo.

As declarações de tempo são valores NumericDate: segundos desde a época Unix, não milissegundos. Isso confunde as pessoas constantemente, porque a maioria dos valores de tempo JavaScript são milissegundos. Um token que parece expirar em 1970 geralmente recebe um valor de milissegundo; aquele que parece expirar no ano 55000 geralmente tem um segundo valor multiplicado por 1000 em algum lugar.

"aud" merece atenção especial quando você está depurando. Um token perfeitamente válido ainda pode ser o token errado, porque foi emitido para um público diferente. Um verificador que verifica a assinatura, mas não o público, aceitará um token cunhado para outro serviço inteiramente – o que é um caminho real de escalonamento de privilégios em sistemas que compartilham um provedor de identidade.

Esta ferramenta renderiza as declarações de tempo em UTC, marca um token expirado como expirado e combina isso com um lembrete de que a declaração de expiração só significa algo se a assinatura for válida. O lembrete existe porque “diz que não expirou” é o momento exato em que o hábito de dados não verificados causa danos.

Uma pequena lista de verificação para o sistema que faz a confiança

Se você estiver escrevendo o código que aceita tokens em vez de apenas inspecionar um, a seguir está uma versão resumida do que um verificador correto faz.

  1. Verifique primeiro a assinatura, com uma chave que você obteve fora da banda, antes de ler qualquer reclamação.
  2. Fixe o algoritmo em sua própria configuração. Nunca leia no cabeçalho do token. Rejeite "nenhum" incondicionalmente.
  3. Verifique "exp" e "nbf" em relação a um relógio confiável, com no máximo uma pequena tolerância para distorção.
  4. Verifique "iss" e "aud" em relação aos valores esperados. Uma assinatura válida em um token destinado a outra pessoa ainda é o token errado.
  5. Use uma biblioteca avaliada para sua plataforma, em vez de montá-la você mesmo. Cada item desta lista está nela porque as implementações erraram.
  6. Mantenha a vida útil do token curta e tenha um caminho de revogação. Os tokens de curta duração limitam os danos do vazamento que você ainda não percebeu.

O que acontece com o que você cola

  • Cada conversão, hash, decodificação e comparação é executada na guia do seu navegador. Nenhuma entrada é carregada, registrada ou armazenada em um servidor, porque não há nenhum servidor envolvido depois que a página é carregada.
  • Hashes vêm da implementação de criptografia da Web do próprio navegador e UUIDs de seu gerador aleatório criptograficamente seguro. Nenhum dos dois envolve uma chamada de rede.
  • Nada do que você digita é gravado no armazenamento local ou em um cookie. Recarregar a página a descarta; fechar a guia a descarta.
  • A análise de todo o site é executada apenas no host de produção canônico configurado e é divulgada na Política de Privacidade; hosts locais e de visualização recusam. Valores colados, tokens, URLs e conteúdos de arquivos são excluídos dos próprios eventos analíticos de ToolAcre. A publicidade está desativada na configuração atual.
  • Dito isto: uma chave JWT ou API é uma credencial ativa. O hábito seguro é nunca colar um em uma página da web que você não escreveu, por mais confiáveis ​​que sejam suas afirmações – incluindo esta.

Questões

Esta ferramenta verifica a assinatura?

Não, e nunca será. Ele decodifica o cabeçalho e a carga útil e mostra o que eles contêm. Ele não verifica a assinatura, portanto, nada que ele exibe prova que o token é autêntico, inalterado ou emitido por quem quer que seja.

Então, como posso saber se um token é genuíno?

Verificando a assinatura com a chave do emissor, usando uma biblioteca verificada, com o algoritmo fixado em sua própria configuração, em vez de lido no token. Isso é trabalho para o serviço que confia no token, em um ambiente que detém legitimamente a chave.

Meu token é enviado para algum lugar quando eu o decodifico aqui?

Não. A decodificação acontece na guia do seu navegador usando o JavaScript da própria página, e a página não faz solicitações de rede após ser carregada. Você pode verificar isso no painel de rede do seu navegador. Você ainda não deve colar tokens de produção em ferramentas da web por uma questão de hábito, porque esse hábito tem que funcionar em sites que não são honestos sobre isso.

Por que alguém pode ler minha carga útil JWT?

Porque a carga útil é codificada em base64url, não criptografada. Um JWS é uma declaração assinada, não lacrada. Se você precisa que o conteúdo seja ilegível, você precisa de JWE, o formato de token criptografado - e então um decodificador não pode mostrar nada sem a chave.

O que é alg: "nenhum"?

Um valor de cabeçalho que declara que o token não está assinado. Existe na especificação para contextos onde a integridade é garantida por outros meios e é uma armadilha permanente: um verificador que confia no algoritmo do cabeçalho aceitará qualquer token que afirme "nenhum". Esta ferramenta sinaliza sempre que aparece.

Meu token tem cinco segmentos e não será decodificado. Por que?

Cinco segmentos significam um JWE — um token criptografado — em vez de um JWS assinado. Seu conteúdo não pode ser lido sem a chave de descriptografia, portanto não há realmente nada para um decodificador mostrar. Esta ferramenta identifica esse caso explicitamente em vez de relatar uma falha de análise vaga.

A expiração parece errada por um fator de 1000.

As declarações de tempo JWT são NumericDate: segundos desde a época, não milissegundos. Um valor produzido por Date.now() é mil vezes grande demais. O utilitário timestamp neste kit de ferramentas converte entre os dois e sempre informa qual unidade foi usada.

É seguro armazenar um JWT em localStorage?

É uma troca, não um sim ou não. localStorage pode ser lido por qualquer JavaScript em execução em sua origem, portanto, uma única vulnerabilidade XSS exfiltra o token. Um cookie httpOnly não pode ser lido por JavaScript, mas precisa de proteção CSRF. O resumo honesto é que nenhum deles é gratuito e a decisão pertence ao modelo de ameaça do seu aplicativo.

Limitações

  • Esta ferramenta decodifica apenas. Ele não verifica assinaturas, e isso é uma decisão de design permanente, e não um recurso ausente – consulte o guia acima para saber o porquê.
  • Os tokens criptografados (JWE, cinco segmentos) não podem ser decodificados sem a chave. A ferramenta os identifica e para.
  • JWTs aninhados — um token cuja carga útil é um token — não são desembrulhados automaticamente. Decodifique o token interno como uma etapa separada.
  • Os significados das declarações além do conjunto registrado definido em RFC 7519 são específicos do aplicativo, portanto a ferramenta mostra seus valores sem interpretá-los.
  • Uma expiração mostrada aqui reflete apenas o que o token afirma sobre si mesmo. Se essa afirmação é significativa depende de uma assinatura que esta ferramenta não verifica.
  • Tokens maiores que 200,000 caracteres são recusados. Qualquer JWT real é muito menor.