Verificar a assinatura de um JSON Web Token (JWT)
- Painel
- Documentação
- API
Porquê verificar a assinatura de um JWT?
Um JSON Web Token (JWT) decompõe-se em três partes separadas por pontos:
header.payload.signature. Descodificar um JWT consiste simplesmente em ler as duas primeiras
partes (que são Base64URL). Qualquer pessoa pode fazê-lo, e qualquer pessoa pode fabricar
um JWT com o payload à sua escolha. O que torna um JWT digno de confiança é unicamente a
assinatura: sem verificação, aceitar um JWT é como deixar entrar em casa qualquer pessoa que
afirme ser alguém, sem pedir documento de identidade.
Esta ferramenta verifica a assinatura de um JWT a partir de uma chave. Não se limita a descodificar: recalcula a assinatura a partir do header, do payload e da sua chave, e depois compara com a assinatura do token. Se as duas coincidirem, o token é autêntico. Caso contrário, foi forjado, modificado, ou assinado com outra chave.
A verificação é a pedra angular de qualquer arquitetura que utilize JWT para
autenticação ou autorização: sem assinatura válida, o payload pode mentir.
Um atacante que modificasse "role":"user" para "role":"admin" não teria qualquer
dificuldade em fazê-lo se o servidor verificasse apenas o formato do token e não a sua assinatura.
Algoritmos comuns
A especificação JWT (RFC 7518, JSON Web Algorithms) define várias famílias de algoritmos. Eis os mais utilizados em produção:
- HMAC (HS256, HS384, HS512): assinatura simétrica à base de HMAC-SHA. A mesma chave secreta serve para assinar e verificar. Simples de implementar, performante, mas qualquer parte capaz de verificar o token também é capaz de o emitir. Adequado a cenários onde o emissor e o verificador são a mesma equipa ou o mesmo serviço.
- RSA (RS256, RS384, RS512): assinatura assimétrica. A chave privada assina, a chave pública verifica. Ideal quando o emissor e os verificadores são entidades distintas (OAuth2, OpenID Connect, federação de identidade). É o algoritmo privilegiado pela maioria dos fornecedores de identidade públicos.
- ECDSA (ES256, ES384): assinatura assimétrica em curvas elípticas. Mesma lógica que RSA (chave privada para assinar, chave pública para verificar) mas com chaves e assinaturas mais compactas para um nível de segurança equivalente. Cada vez mais difundido nas arquiteturas modernas.
Como fornecer a chave
O formato da chave esperada depende do algoritmo declarado no header do JWT:
- HS256, HS384, HS512: a chave é uma cadeia secreta (string).
É o segredo partilhado com o emissor, frequentemente armazenado numa variável de ambiente como
JWT_SECRET. Sem formatação particular, apenas o valor bruto. - RS256, RS384, RS512: a chave é uma chave pública RSA em formato PEM,
que começa por
-----BEGIN PUBLIC KEY-----e termina por-----END PUBLIC KEY-----. Conserve as quebras de linha tal como estão, caso contrário o OpenSSL recusa fazer parse. - ES256, ES384: a chave é uma chave pública ECDSA em formato PEM, na curva correspondente (P-256 para ES256, P-384 para ES384).
Exemplo de chave pública RSA esperada
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxe...
...vQIDAQAB
-----END PUBLIC KEY-----
Como funciona a verificação?
O nosso servidor reproduz exatamente a operação que o emissor fez:
- Separa o JWT em header, payload e signature.
- Concatena
base64url(header) + "." + base64url(payload). - Para HMAC, calcula um HMAC-SHA-256/384/512 com a sua chave secreta, depois compara com a
assinatura recebida através de
hash_equals(comparação em tempo constante para evitar ataques temporais). - Para RSA, chama
openssl_verifycom a sua chave pública em formato PEM.
Casos de uso
- Debug de autenticação de API: recebe um 401, verifique se o seu token está mesmo assinado com a chave esperada.
- Validação de um token recebido de um fornecedor: um parceiro (Auth0, Keycloak, Cognito, Okta) envia-lhe JWTs assinados em RS256; quer confirmar que vêm mesmo dele com a sua chave pública.
- Auditoria de segurança: verificar que um serviço terceiro assina corretamente os seus tokens com um algoritmo robusto, e não em HS256 com um segredo fraco.
- Testes manuais: verificar que um JWT gerado pelo seu código passa bem a verificação com a chave pública fornecida.
- Verificação rápida de um token recebido: durante a integração de um SSO ou de uma API parceira, verificar em segundos que a cadeia assinatura/chave funciona antes de escrever a primeira linha de código.
Como utilizar a ferramenta
- Cole o JWT completo (as três partes separadas por pontos).
- Indique a chave adequada ao algoritmo do header:
- Para HS256, HS384 ou HS512, a chave é a cadeia secreta
partilhada com o emissor. É uma cadeia livre, frequentemente armazenada numa
variável de ambiente como
JWT_SECRET. - Para RS256, RS384 ou RS512, a chave é a chave pública em formato
PEM, que começa por
-----BEGIN PUBLIC KEY-----e termina por-----END PUBLIC KEY-----.
- Para HS256, HS384 ou HS512, a chave é a cadeia secreta
partilhada com o emissor. É uma cadeia livre, frequentemente armazenada numa
variável de ambiente como
- Inicie a verificação. A ferramenta mostra o estado (válido ou inválido) e o payload descodificado.
Armadilhas comuns a evitar
- Algoritmo "none": a spec permite
alg: none, que significa "sem assinatura". Uma falha clássica consiste em fabricar um token com este header esperando que o servidor o aceite. A nossa ferramenta rejeita sistematicamente os tokens comalg: none. - Confusão HMAC vs RSA (algorithm confusion): um atacante muda o algoritmo
RS256paraHS256e assina o payload com a chave pública RSA utilizada como segredo HMAC. Se o servidor não controlar o algoritmo, aceita o token. Bloqueie sempre o algoritmo esperado no servidor. - Segredos HMAC em código: um segredo commitado num repositório Git torna toda a confiança dos tokens caduca. Armazene os segredos em variáveis de ambiente ou num cofre aplicacional.
- Chave pública vs chave privada: para verificar um JWT assinado em RSA ou ECDSA, fornece-se a chave pública, nunca a privada. A privada só serve para assinar e nunca deve sair do emissor.
- Expiração ignorada: uma assinatura válida num token expirado nunca
deve ser aceite. Pense em verificar
expenbf. - Audiência não controlada: um token destinado à API A não deveria ser aceite
pela API B. Verifique a claim
aud.
Claims temporais: exp e nbf
Para além da assinatura, um JWT válido deve também respeitar as suas restrições temporais:
- exp (expiration): o token deixa de ser válido após esta data.
- nbf (not before): o token ainda não é válido antes desta data.
A nossa ferramenta sinaliza explicitamente quando um token está expirado ou ainda não válido, mesmo que a sua assinatura esteja correta. É importante: uma assinatura válida num token expirado nunca deve ser aceite em produção.
Diferença com o nosso JWT decoder
O nosso JWT decoder limita-se a descodificar as partes header e payload para as tornar legíveis. Não efetua qualquer verificação de assinatura e não pede chave. Utilize-o para inspecionar rapidamente o conteúdo de um token. Utilize o JWT verifier (esta página) assim que precisar de provar que um token é autêntico. Para fabricar um JWT assinado para fins de teste, utilize o nosso JWT builder.
Perguntas frequentes
Porquê RS256 em vez de HS256?
Com HS256, o emissor e o verificador partilham o mesmo segredo: qualquer verificador pode portanto emitir tokens. É gerível quando se controla os dois lados. Assim que se fala de um fornecedor de identidade único com vários serviços consumidores, passa-se a RS256: o emissor guarda a chave privada, distribui-se a chave pública a todas as APIs que devem verificar. Nenhuma API consumidora pode então forjar tokens.
Como obter a chave pública de um fornecedor de identidade (IdP)?
A maioria dos IdP expõe um endpoint JWKS padronizado (por exemplo
https://exemplo.com/.well-known/jwks.json). Este endpoint devolve um JSON que contém
as chaves públicas ativas. Pode converter a entrada JWK que corresponde ao kid
do header do seu JWT em chave PEM através do comando openssl ou de uma biblioteca
JWKS da sua stack (por exemplo jose-jwt, jwks-rsa).
Que fazer se o verify falhar?
Verifique primeiro o algoritmo: um token assinado em HS256 não se verifica com uma chave RSA, e
inversamente. Verifique depois a chave: um caractere branco a mais, uma quebra de linha em falta
numa chave PEM, ou um segredo HMAC ligeiramente diferente do utilizado pelo emissor
bastam para fazer falhar a verificação. Se o IdP efetuou uma rotação de chave, o seu
kid pode apontar para uma chave que já não tem.
JWKS, o que é?
JWKS (JSON Web Key Set, RFC 7517) é um formato JSON que descreve um conjunto de
chaves públicas. Cada chave é identificada por um kid (key ID) e o JWT a verificar
referencia esse kid no seu header. O mecanismo permite ao IdP fazer rodar as suas
chaves sem partir os verificadores: estes interrogam simplesmente o endpoint JWKS para obter a
chave correspondente ao kid do token recebido.
Como gerar um par de chaves RSA para assinar os meus JWT?
Com OpenSSL: openssl genrsa -out private.pem 2048 depois
openssl rsa -in private.pem -pubout -out public.pem. A chave privada assina no lado do
emissor, a chave pública verifica no lado do consumidor. Para novos serviços, prefira 3072 ou
4096 bits.
É preciso cifrar o JWT além de o assinar (JWE)?
Um JWT assinado (JWS) garante a integridade e a autenticidade, mas o payload continua legível por quem o recupere. Se o token contém dados sensíveis (identificadores internos, direitos detalhados, dados pessoais), considere o formato JWE (JSON Web Encryption) que cifra o payload além de o assinar.
Exemplo de pedido
curl -X POST https://cdrn.fr/api/v1/tools/jwt-verifier/execute \
-H "Content-Type: application/json" \
-d '{"token":"...","key":"..."}'
Esquema de entrada
| Campo | Tipo | Obrigatório | Predefinição |
|---|---|---|---|
token |
text | ✓ | – |
key |
text | ✓ | – |
Pontos de acesso
GET https://cdrn.fr/api/v1/tools- lista todas as ferramentas disponíveisGET https://cdrn.fr/api/v1/tools/jwt-verifier- obtém o esquema desta ferramentaPOST https://cdrn.fr/api/v1/tools/jwt-verifier/execute- executa esta ferramenta com um payload JSON