Um JWT são três segmentos codificados em base64url e separados por pontos: o cabeçalho que nomeia o algoritmo, o payload com as claims e a assinatura que prova que cabeçalho e payload não foram adulterados depois da emissão. Decodificar mostra o que o token diz. Verificar prova que ele continua confiável. Esta ferramenta faz as duas coisas, roda inteiramente no seu navegador e nunca gera nem assina um token — não há caminho com chave aqui para um atacante explorar.
Três segmentos, dois deles legíveis
A RFC 7519 define o formato compacto do JWT. Cabeçalho e payload são objetos JSON, cada um codificado em base64url conforme a RFC 4648 §5 — a variante URL-safe que troca + por -, / por _ e elimina o padding =. A assinatura é o MAC ou a assinatura digital sobre a string header.payload concatenada, ela mesma codificada em base64url. Aplique decodeJwt no exemplo canônico da RFC 7519 §3.1 e você obtém cabeçalho { "typ": "JWT", "alg": "HS256" } e payload { "iss": "joe", "exp": 1300819380, "http://example.com/is_root": true }.
base64url não é criptografia. Qualquer pessoa que leia a URL lê o payload — esse é o objetivo. JWTs são à prova de adulteração, não confidenciais. Se você colocou um segredo de sessão, um telefone ou um identificador interno dentro do payload, você publicou esse dado. Use JWE (RFC 7516) quando precisar de confidencialidade. Este decoder lê JWS apenas; tokens criptografados (JWE) estão fora do escopo.
As claims registradas e o que elas significam de fato
As sete claims registradas no IANA (RFC 7519 §4.1) são as únicas com semântica portável entre bibliotecas: iss (issuer), sub (subject), aud (audience), exp (expiração, NumericDate em segundos desde a época), nbf (not-before), iat (issued-at) e jti (identificador único para defesa contra replay). Tudo o resto é claim pública ou privada — a spec é deliberada em não prescrever em excesso. O widget lista as registradas primeiro, na ordem da RFC, depois as suas claims customizadas na ordem em que aparecem, e formata exp / iat / nbf como timestamps ISO com uma dica de tempo relativo — um token expirado salta na cara.
Um token está expirado quando exp × 1000 ≤ agora. A checagem é local à sua máquina e ao instante em que você abriu a página — não há negociação de drift de relógio. Se o seu serviço rejeita um token que o decoder mostra válido por alguns segundos, a diferença é entre o relógio do seu servidor e o do emissor, não um bug do decoder.
HS, RS, PS, ES — e por que o alg importa
A RFC 7518 cataloga todos os algoritmos que um JWS pode usar. As três famílias relevantes na prática são HMAC (HS256, HS384, HS512) com um segredo simétrico compartilhado; RSASSA-PKCS1-v1_5 (RS256, RS384, RS512) e sua versão com padding PSS (PS256, PS384, PS512) usando um par de chaves RSA; e ECDSA (ES256 na curva P-256, ES384 na P-384) usando par de chaves de curva elíptica. HMAC simétrico é o mais fácil de operacionalizar — os dois lados guardam o mesmo segredo. As variantes assimétricas existem quando o verificador não deve poder emitir tokens, que é o caso normal em arquiteturas OAuth: o servidor de autorização assina com a chave privada e os servidores de recurso verificam com a pública correspondente.
O painel de verificação roteia por família. HMAC recebe o segredo como bytes brutos via SubtleCrypto.importKey("raw", …). RSA, RSA-PSS e ECDSA recebem uma chave pública em PEM, e o widget retira o invólucro -----BEGIN PUBLIC KEY-----, decodifica o base64 para bytes SPKI DER e entrega para importKey("spki", …). Chaves privadas são rejeitadas no parser — você não consegue colar uma chave de assinatura por engano no verificador.
Dois ataques conhecidos que o decoder não esconde de você
O primeiro é alg=none. Um JWT com {"alg":"none"} no cabeçalho não carrega assinatura nenhuma (o terceiro segmento é vazio). A spec original permite isso em contextos não assinados, mas para tokens em produção é uma vulnerabilidade: uma biblioteca que "verifica" um token alg=none pulando a checagem da assinatura aceita qualquer coisa. O OWASP JWT cheat-sheet sinaliza isso desde 2015 e a Web Security Academy do PortSwigger ainda usa esse caso como exercício de teaching. O widget mostra uma faixa vermelha INSECURE no instante em que o cabeçalho é parseado como none, e o pipeline de verificação recusa retornar resultado.
O segundo é algorithm confusion. Um verificador vulnerável que alterna entre RS256 (assimétrico, chave pública RSA) e HS256 (simétrico, segredo compartilhado) confiando no alg auto-declarado do token pode ser induzido a usar os bytes da chave pública RSA como segredo HMAC. Quem leia a chave pública forja tokens. A mitigação do lado do servidor é uma allow-list estrita: um verificador configurado para RS256 trata token HS256 como malformado, ponto final. Este decoder mostra o alg declarado, a família para a qual ele rotearia e como o material de chave é interpretado — você identifica a divergência na hora.
Por que Web Crypto, por que client-side
O SubtleCrypto do Web Crypto existe em todo browser evergreen e no Node 18+. É a mesma primitiva que a sua biblioteca de autenticação usa no servidor, acessível dentro da página. A chamada de verify é um subtle.verify() contra uma chave devolvida por importKey(), e a matemática roda na implementação nativa de cripto do host, não em JavaScript. Isso compra comparações em tempo constante contra timing attacks na checagem de assinatura, aceleração por hardware em plataformas que oferecem, e uma única superfície de auditoria atravessando browsers e Node.
O decoder usa Web Crypto só para verificar. Não há caminho de assinatura no código-fonte — busque por subtle.sign no repositório e você só encontra em arquivos de teste gerando vetores de round-trip para o verificador. Seu segredo ou chave privada, caso você cole um por engano, vive em state local do componente React pelo tempo de vida da aba e nunca é gravado em localStorage, sessionStorage ou em qualquer egresso de rede.
O que a página faz com o seu token
O JWT de entrada, o segredo e a chave pública são processados integralmente na aba do navegador. Cabeçalho, payload e assinatura decodificados vivem no state do componente. O painel de histórico recente persiste a string do JWT — base64url não é segredo, é byte público — sob a chave de escopo recent-inputs:jwt-decoder:v1, junto com um rótulo de variante (decoded ou decoded-verified) e um timestamp. O segredo de verificação e qualquer PEM colado nunca são escritos nesse armazenamento; um teste em tempo de execução varre todo o localStorage depois de uma verify para garantir que os bytes do segredo não aparecem em disco. Recarregar uma entrada do histórico repete só o JWT — o campo de segredo é limpo e você precisa reentrar.
JWT em fintech brasileira: Open Finance e FAPI
No Brasil, o uso mais regulado de JWT está no Open Finance Brasil, que herdou os padrões do antigo Open Banking e segue a especificação FAPI-1.0 Part 2 Advanced. As instituições autorizadas pelo Bacen autenticam clientes de API por mTLS e private_key_jwt simultaneamente — o JWS assinado entra como prova de posse da chave privada cadastrada no diretório. A Instrução Normativa BCB nº 134/2021 referencia os padrões técnicos de segurança que regem essa cadeia. Na prática, é o decoder que você usa para conferir uma request object assinada antes de subir uma integração em sandbox, e o verify panel responde "valid" ou "invalid" sem você precisar instalar o openssl numa máquina compartilhada.
Onde isso justifica o tempo
A sessão típica de debug dura dois minutos: cola um token de um cabeçalho HTTP, lê as claims, confere se exp passou, copia sub para uma query no banco. As ferramentas vizinhas cobrem a camada de codificação — o Codificador/Decodificador Base64 é a mesma foundation base64url que este decoder consome, e o Gerador de Hash é exatamente o que a família HMAC desta página chama por baixo. Para pipelines de CI que tocam credenciais, cole o segredo de assinatura ou a chave pública, rode o JWT e o verify panel diz se a assinatura está íntegra antes de você fazer deploy de uma rotação de chave.

