Definição
Os JWT / JWS / JWE formam uma família de padrões IETF (RFC 7515 a 7519, 2015) que define um formato compacto, URL-safe e portável para transportar claims (asserções) assinados e/ou criptografados em formato JSON.
É o componente fundamental da autenticação moderna (access tokens OAuth, ID Tokens OIDC), da assinatura aplicacional e do transporte seguro de dados estruturados (webhooks assinados, atestações).
| Padrão | RFC | Papel |
|---|---|---|
| JWT | 7519 | Formato geral (claims JSON codificados) |
| JWS | 7515 | Assinatura (integridade, autenticidade) |
| JWE | 7516 | Criptografia (confidencialidade) |
| JWA | 7518 | Algoritmos (HS256, RS256, A256GCM…) |
| JWK | 7517 | Representação das chaves em JSON |
Formato JWT (assinado = JWS)
Três partes separadas por pontos:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNzE0MDAwMDAwfQ
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c- Header (base64url):
{"alg":"HS256","typ":"JWT"} - Payload (base64url):
{"sub":"1234567890","name":"Alice","iat":1714000000} - Assinatura: HMAC ou RSA/ECDSA conforme o
alg
Os claims padrão: iss (emissor), sub (sujeito), aud (destinatário), exp (expiração), nbf (not before), iat (issued at), jti (identificador único anti-replay), além de claims privados (email, roles, scope).
Algoritmos de assinatura (JWS)
| Algo | Tipo | Uso típico |
|---|---|---|
HS256 | HMAC simétrico | Testes, monolitos |
RS256 | RSA assimétrico | OAuth, OIDC clássico |
PS256 | RSA-PSS | Recomendado para FAPI (Open Banking) |
ES256 | ECDSA P-256 | Recomendado para FAPI, mobile |
EdDSA | Ed25519 | Moderno, rápido |
none | Nenhuma assinatura | Proibido (falha histórica) |
Boas práticas: preferir o assimétrico (chave pública compartilhável) para as APIs públicas, privilegiar PS256/ES256, nunca aceitar alg: none e sempre verificar o alg esperado no servidor em vez de confiar no header.
JWE (criptografia)
O JWE criptografa o payload (confidencialidade) além da integridade, em 5 partes: header.encrypted_key.iv.ciphertext.tag. Key encryption comum: RSA-OAEP, ECDH-ES, A256KW; content encryption: A256GCM, A128CBC-HS256. Uso: transporte de dados secretos (cartão tokenizado, dados de KYC) entre serviços.
JWT vs sessão tradicional
| Aspecto | Cookie de sessão | JWT |
|---|---|---|
| Estado | Servidor | Cliente (stateless) |
| Escalabilidade | Sticky session ou BD compartilhado | Trivial |
| Revogação | Exclusão server-side | Difícil (blacklist) |
| Legibilidade | Opaco | Legível (base64url) |
| Risco de roubo | Cookie httpOnly | Bearer = portador |
Casos de uso
- OAuth / OIDC: access token (muitas vezes JWT; o FAPI exige um JWT assinado e bindado), ID Token (sempre JWT assinado), Request Object JAR (JWT assinado).
- API: bearer JWT no
Authorization, verificado via chave pública (endpoint JWKS). - Webhooks: Stripe, GitHub e Slack assinam em JWS.
- Identidade / KYC: Verifiable Credentials da W3C e SD-JWT (disclosure seletivo) para o EUDI Wallet.
- eIDAS: JAdES, perfil de assinatura qualificada baseado em JWS.
Ataques conhecidos
alg: none: algumas bibliotecas antigas aceitavam um payload não verificado.- Confusão de algoritmo (HS256 vs RS256): assinar com a chave pública RSA como segredo HMAC, se o servidor não fixar o
alg. - Injeção de
kid: umkidmal validado pode abrir uma SQL injection ou um path traversal. - Replay: um JWT roubado permanece válido até o
exp(mitigação:jti+ cache, tokens curtos). - Vazamento de informação: o payload é legível — não colocar nele nenhum dado sensível, criptografar em JWE se necessário.
Boas práticas
Preferir PS256/ES256, tokens curtos (5-15 min, refresh longo), tokens bindados ao cliente (mTLS, DPoP) no FAPI; verificar sistematicamente iss, aud, exp, nbf e alg; rotacionar as chaves (JWKS); evitar PII em texto puro (JWE se necessário); auditar regularmente as dependências (CVE).
O que JWT / JWS / JWE não é
- Não é uma criptografia de transporte: é aplicacional, o TLS continua necessário.
- Não é uma sessão: um token, em geral curto e stateless.
- Não é uma senha: um token de acesso emitido após a autenticação.
- Não é revogável nativamente: válido até a expiração, salvo blacklist mantida.
No ecossistema PSD2 / Open Finance
JWT e JWS são onipresentes: access tokens OAuth na PSD2, ID Tokens OIDC (FranceConnect, EUDI Wallet), Request Objects JAR no FAPI, webhooks assinados (Bridge, Tink, Plaid) e Verifiable Credentials EUDI em SD-JWT.
Exemplos concretos
- Webhooks Stripe: assinados em HMAC SHA-256, formato próximo do JWS.
- Auth0, Okta, Cognito: emitem JWTs.
- OBIE UK: access tokens e ID Tokens em JWT PS256.
- EUDI Wallet: credentials em SD-JWT (provar "maior de idade" sem revelar a data de nascimento).
- FranceConnect: ID Tokens JWT.
- Vulnerabilidade de 2018: a falha de "confusão de algoritmo" corrigida globalmente nas bibliotecas.
- Ferramentas: jwt.io (debugger),
jose(JS), PyJWT, java-jwt, jose4j.