JWT Explicado do Jeito Certo
JWT virou padrão em APIs modernas. Mas a verdade é que muita aplicação usa JWT errado.
Tem sistema:
sem refresh token
guardando token inseguro
sem expiração
vulnerável
impossível de escalar
E pior: muita gente copia tutorial do YouTube de 15 minutos e joga em produção.
Aí nasce o caos.
Neste artigo vamos entender JWT do jeito profissional.
O que é JWT?
JWT significa:
JSON Web Token
É um token compacto usado para:
autenticação
autorização
troca segura de informações
Exemplo:
eyJhbGciOiJIUzI1NiJ9...O token possui 3 partes:
HEADER.PAYLOAD.SIGNATUREEstrutura do JWT
Header
Define algoritmo:
{
"alg": "HS256",
"typ": "JWT"
}Payload
Dados do usuário:
{
"sub": "anderson@email.com",
"role": "ADMIN",
"exp": 1746699999
}Nunca coloque:
senha
CPF
cartão
dados sensíveis
JWT NÃO é criptografado. Ele é apenas assinado.
Signature
Garante integridade:
HMACSHA256(
base64UrlEncode(header) +
"." +
base64UrlEncode(payload),
secret
)Fluxo correto de autenticação
Fluxo profissional:
Usuário faz login
API valida credenciais
API gera:
access token
refresh token
Frontend salva token
Requisições usam Bearer Token
Access token expira
Refresh token gera novo access token
Access Token vs Refresh Token
Access Token
Vida curta:
5 min
15 min
30 min
Usado nas requisições.
Refresh Token
Vida longa:
7 dias
30 dias
Usado apenas para renovar sessão.
Por que isso importa?
Porque se roubarem:
access token → dano limitado
refresh token → precisa revogação
Segurança real vem daqui.
Implementação correta no Spring Boot
Dependências
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>Gerando token
public String generateToken(UserDetails user) {
Date now = new Date();
Date expiration = new Date(
now.getTime() + 1000 * 60 * 15
);
return Jwts.builder()
.setSubject(user.getUsername())
.claim("role", "ADMIN")
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(secretKey, SignatureAlgorithm.HS256)
.compact();
}Validando token
public boolean isValid(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token);
return true;
} catch (Exception ex) {
return false;
}
}Filter JWT no Spring Security
@Component
public class JwtAuthenticationFilter
extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) {
String authHeader =
request.getHeader("Authorization");
if(authHeader == null ||
!authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
String token =
authHeader.substring(7);
filterChain.doFilter(request, response);
}
}Onde salvar token no React?
ERRADO
localStoragePor quê?
vulnerável a XSS
CERTO
httpOnly cookies OU
memória + refresh controlado
Erros clássicos com JWT
1. Token eterno
Isso é bomba relógio.
2. Não invalidar refresh token
Usuário faz logout. Token continua funcionando.
Perigo enorme.
3. Guardar informações sensíveis
JWT não é cofre.
4. Chave fraca
Esse erro é clássico:
WeakKeyExceptionTamanho correto da chave
HS256: mínimo 256 bits.
JWT em microserviços
Arquitetura comum:
Auth Service
API Gateway
Microservices validam token
Benefícios:
stateless
escalável
rápido
Quando NÃO usar JWT?
Nem tudo precisa JWT.
Exemplos:
sistemas internos simples
monolitos pequenos
aplicações server-side tradicionais
Às vezes session/cookie resolve melhor.
E tá tudo bem.
JWT vs Session
JWT | Session |
|---|---|
Stateless | Stateful |
Escalável | Mais simples |
Melhor APIs | Melhor server-side |
Complexo | Fácil |
Muito usado em microserviços | Muito usado em monolitos |
Conclusão
JWT é excelente.
Mas JWT mal implementado:
vira problema
vira vulnerabilidade
vira retrabalho
A implementação profissional precisa:
refresh token
expiração curta
revogação
storage seguro
filtros corretos
rotação de token
Autenticação não é detalhe. É fundação do sistema.
