Guia Completo de JWT 2026 - Estrutura, Seguranca e Melhores Praticas
Da estrutura e funcionamento do JSON Web Token a vulnerabilidades de seguranca e melhores praticas. Domine a autenticacao JWT com exemplos de codigo praticos.
Toolypet Team
Development Team
Guia Completo de JWT 2026
"JWT? Nao e apenas um token?"
Sim, e. Mas quando esse "simples token" nao e implementado corretamente, torna-se um problema serio de seguranca. De acordo com estudos de 2026, 48% do codigo de autenticacao gerado por IA contem vulnerabilidades de seguranca.
Este guia cobre tudo, desde a estrutura do JWT ate as melhores praticas de seguranca.
O que e JWT?
JWT (JSON Web Token) e um metodo compacto e autocontido para transmitir informacoes de forma segura entre duas partes.
Caracteristicas Principais
| Caracteristica | Descricao |
|---|---|
| Stateless | Nao requer armazenamento de sessao no servidor |
| Self-contained | Toda informacao necessaria esta no token |
| Compact | Utilizavel em URLs, headers HTTP |
| Signed | Pode detectar adulteracao |
Casos de Uso
- Autenticacao API: Requisicoes API com Bearer token
- SSO (Single Sign-On): Compartilhar autenticacao entre multiplos servicos
- Troca de informacoes: Transmissao de dados assinados
- Authorization: Incluir informacoes de permissoes/roles
Estrutura do JWT
JWT consiste em tres partes codificadas em Base64URL separadas por . (pontos).
xxxxx.yyyyy.zzzzz
| | |
Header Payload Signature
1. Header
{
"alg": "HS256",
"typ": "JWT"
}
| Campo | Descricao |
|---|---|
alg | Algoritmo de assinatura (HS256, RS256, etc.) |
typ | Tipo de token (JWT) |
2. Payload (Claims)
{
"sub": "user123",
"name": "Joao Silva",
"email": "joao@example.com",
"role": "admin",
"iat": 1708502400,
"exp": 1708588800
}
Claims Registrados
| Claim | Descricao | Exemplo |
|---|---|---|
iss | Emissor (Issuer) | "https://auth.example.com" |
sub | Sujeito (Subject) | "user123" |
aud | Audiencia (Audience) | "https://api.example.com" |
exp | Tempo de expiracao | 1708588800 |
nbf | Nao antes de (Not Before) | 1708502400 |
iat | Emitido em (Issued At) | 1708502400 |
jti | ID unico do JWT | "abc123" |
Claims Publicos/Privados
{
"role": "admin", // Claim privado
"email": "user@example.com",
"permissions": ["read", "write"]
}
3. Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Algoritmos de Assinatura
Chave Simetrica
| Algoritmo | Descricao | Caso de Uso |
|---|---|---|
| HS256 | HMAC + SHA-256 | Servidor unico, implementacao simples |
| HS384 | HMAC + SHA-384 | Maior seguranca |
| HS512 | HMAC + SHA-512 | Seguranca de nivel maximo |
// Node.js - HS256
const jwt = require('jsonwebtoken');
const token = jwt.sign(
{ userId: 123, role: 'admin' },
'your-256-bit-secret', // Verificado com o mesmo segredo
{ algorithm: 'HS256', expiresIn: '1h' }
);
Chave Assimetrica
| Algoritmo | Descricao | Caso de Uso |
|---|---|---|
| RS256 | RSA + SHA-256 | Microsservicos, verificacao publica |
| RS384 | RSA + SHA-384 | Requisitos de alta seguranca |
| RS512 | RSA + SHA-512 | Seguranca de nivel maximo |
| ES256 | ECDSA + P-256 | Chaves curtas, movel |
// RS256 - Assimetrico
const privateKey = fs.readFileSync('private.pem');
const publicKey = fs.readFileSync('public.pem');
// Emissao (Private Key)
const token = jwt.sign(payload, privateKey, { algorithm: 'RS256' });
// Verificacao (Public Key)
const decoded = jwt.verify(token, publicKey, { algorithms: ['RS256'] });
Guia de Selecao de Algoritmo
| Cenario | Algoritmo Recomendado |
|---|---|
| Servidor unico | HS256 |
| Microsservicos | RS256 |
| Verificacao publica necessaria | RS256 / ES256 |
| Movel/IoT | ES256 (chaves curtas) |
Implementacao Pratica
Node.js (Express)
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const SECRET = process.env.JWT_SECRET; // Carregar da variavel de ambiente
// Emissao de token
app.post('/login', async (req, res) => {
const { email, password } = req.body;
// Verificacao de usuario (exemplo)
const user = await verifyCredentials(email, password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign(
{
sub: user.id,
email: user.email,
role: user.role,
},
SECRET,
{
expiresIn: '1h',
issuer: 'your-app-name',
}
);
res.json({ token });
});
// Verificacao com middleware
const authMiddleware = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Missing token' });
}
const token = authHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, SECRET, {
issuer: 'your-app-name',
algorithms: ['HS256'],
});
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
};
// Rota protegida
app.get('/protected', authMiddleware, (req, res) => {
res.json({ message: `Hello, ${req.user.email}` });
});
Python (FastAPI)
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from datetime import datetime, timedelta
import os
app = FastAPI()
security = HTTPBearer()
SECRET = os.environ.get("JWT_SECRET")
# Emissao de token
def create_token(user_id: str, role: str) -> str:
payload = {
"sub": user_id,
"role": role,
"iat": datetime.utcnow(),
"exp": datetime.utcnow() + timedelta(hours=1),
}
return jwt.encode(payload, SECRET, algorithm="HS256")
# Verificacao de token
def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
try:
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expired")
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail="Invalid token")
# Endpoint protegido
@app.get("/protected")
def protected_route(user: dict = Depends(verify_token)):
return {"message": f"Hello, {user['sub']}"}
Vulnerabilidades de Seguranca e Contramedidas
1. Ataque Algorithm None
// Header malicioso
{
"alg": "none",
"typ": "JWT"
}
Contramedida:
// Especificar algoritmos permitidos
jwt.verify(token, secret, { algorithms: ['HS256'] }); // OK
jwt.verify(token, secret); // Perigoso
2. Chave Secreta Fraca
// Perigoso
const SECRET = 'secret123';
// Seguro (minimo 256 bits)
const SECRET = crypto.randomBytes(32).toString('hex');
3. Exposicao de Informacoes Sensiveis
// Perigoso: Payload pode ser decodificado em Base64
{
"password": "user_password", // Nunca faca isso!
"creditCard": "1234-5678-9012-3456"
}
// Seguro
{
"sub": "user123",
"role": "admin"
}
4. Roubo de Token
Estrategias de contramedida:
- Tempo de expiracao curto (15 min ~ 1 hora)
- Usar Refresh Token
- HTTPS obrigatorio
- Cookies HttpOnly (prevencao XSS)
5. Ataque de Replay JWT
// Usar jti (JWT ID)
const token = jwt.sign({
sub: user.id,
jti: crypto.randomUUID(), // ID unico
}, SECRET);
// Gerenciar lista negra de jti no servidor
Access Token + Refresh Token
Por que e necessario?
| Token | Duracao | Proposito |
|---|---|---|
| Access Token | 15 min ~ 1 hora | Autenticacao API |
| Refresh Token | 7 ~ 30 dias | Renovar Access Token |
Exemplo de Implementacao
// Emitir ambos tokens no login
app.post('/login', async (req, res) => {
const user = await verifyCredentials(req.body);
const accessToken = jwt.sign(
{ sub: user.id, type: 'access' },
ACCESS_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ sub: user.id, type: 'refresh' },
REFRESH_SECRET,
{ expiresIn: '7d' }
);
// Refresh Token como cookie HttpOnly
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
});
// Renovacao de token
app.post('/refresh', (req, res) => {
const refreshToken = req.cookies.refreshToken;
try {
const decoded = jwt.verify(refreshToken, REFRESH_SECRET);
const newAccessToken = jwt.sign(
{ sub: decoded.sub, type: 'access' },
ACCESS_SECRET,
{ expiresIn: '15m' }
);
res.json({ accessToken: newAccessToken });
} catch (err) {
res.status(401).json({ error: 'Invalid refresh token' });
}
});
Depuracao de JWT
Decodificacao de Token
Cole seu token no JWT Decoder para:
- Verificar Header
- Verificar Payload
- Verificar tempo de expiracao
- Verificar assinatura (quando segredo e fornecido)
Decodificacao CLI
# Decodificar Header
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" | base64 -d
# Decodificar Payload
echo "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4ifQ" | base64 -d
Lista de Verificacao de Melhores Praticas
Emissao
- Chave secreta forte (256 bits ou mais)
- Especificar algoritmo (HS256, RS256)
- Tempo de expiracao curto (15 min ~ 1 hora)
- Incluir claims obrigatorios (sub, iat, exp, iss)
- Sem informacoes sensiveis
Verificacao
- Lista branca de algoritmos (
algorithms: ['HS256']) - Validacao de tempo de expiracao
- Validacao de emissor (iss)
- Validacao de audiencia (aud)
Armazenamento e Transmissao
- HTTPS obrigatorio
- Cookie HttpOnly (prevencao XSS)
- Atributo SameSite (prevencao CSRF)
- Evitar localStorage (vulneravel a XSS)
Perguntas Frequentes
Q1: JWT vs Session, quando usar qual?
R:
- JWT: API stateless, microsservicos, apps moveis
- Session: Apps web tradicionais, renderizacao do lado do servidor, logout imediato necessario
Q2: E se o JWT for roubado?
R: Access Token permanece valido ate expirar. Portanto:
- Definir tempo de expiracao curto (15 min)
- Refresh Token Rotation
- Invalidar todos os tokens quando houver suspeita
Q3: Por que nao devo armazenar em localStorage?
R: E vulneravel a ataques XSS. Como JavaScript pode acessar, scripts maliciosos podem roubar tokens. Cookies HttpOnly sao mais seguros.
Q4: RS256 e mais seguro que HS256?
R: Nao e "mais seguro" mas "proposito diferente".
- HS256: Mesmo segredo compartilhado, servidor unico
- RS256: Verificar com chave publica, multiplos servicos
Q5: Preciso de uma lista negra de tokens?
R: Se voce precisa de logout imediato, sim. Mas reduz a vantagem de stateless. Expiracao curta + Refresh Token e uma alternativa.
Conclusao
Pontos-chave de seguranca JWT:
- Segredo forte: 256 bits ou mais aleatorios
- Verificacao de algoritmo: Abordagem de lista branca
- Duracao curta: Access 15 min, Refresh 7 dias
- Armazenamento seguro: Cookies HttpOnly + Secure
- Sem info sensivel: Payload e decodificavel por qualquer um
Ferramentas Relacionadas
| Ferramenta | Proposito |
|---|---|
| JWT Decoder | Decodificacao e verificacao JWT |
| Base64 Encoder | Codificacao/decodificacao Base64 |
| Hash Generator | Geracao de hash |
Sobre o Autor
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.