🔒 Cap 02: Autenticação e Autorização Ponta a Ponta: JWT, Refresh Tokens, Cookies HTTP-Only e RBAC
Arquitetura de Aplicações Full Stack
🗺️ Mapa Conceitual
flowchart LR
BROWSER["🌐 Navegador"] -->|"1. POST /login (credenciais)"| API["🏛️ Backend Auth Service"]
API -->|"2. Retorna Access Token (Memória) + Refresh Token (Cookie HTTP-Only)"| BROWSER
BROWSER -->|"3. Requisição Protegida (Header Bearer JWT)"| API
API -->|"4. Valida Roles (RBAC: ADMIN / USER)"| DB["PostgreSQL"]
style BROWSER fill:#e1f5fe,stroke:#03a9f4,stroke-width:1px
style API fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
style DB fill:#fff3e0,stroke:#ff9800,stroke-width:1px
🧩 Sessão × token
- HTTP não lembra de ninguém: toda requisição traz uma prova de identidade
- Sessão: o servidor guarda o estado; logout imediato
- JWT: o servidor só confere a assinatura; ideal para vários clientes e serviços
🔑 Anatomia do JWT
cabeçalho.payload.assinaturaem Base64URL- Claims:
sub,iat,exp,roles - Assinado, não criptografado: qualquer um lê o payload → nada sensível nele
- HS256 (uma chave) × RS256 (privada assina, pública verifica)
🔄 Access + refresh token
| Access | Refresh | |
|---|---|---|
| Vida | 5–15 min | Dias |
| Onde fica | Memória | Cookie HttpOnly |
| Vai para | Toda requisição | Só /api/auth/refresh |
Rotação: cada uso do refresh gera um novo e invalida o anterior
🍪 O cookie do refresh token
refresh_token=...; HttpOnly; Secure; SameSite=Strict; Path=/api/auth/refresh; Max-Age=604800
HttpOnly→ o JS não lê (XSS)Secure→ só HTTPSSameSite=Strict→ outros sites não o enviam (CSRF)
🛡️ Backend: filtro + RBAC
OncePerRequestFilterlêAuthorization: Bearer, valida e preenche oSecurityContext- API
STATELESS; rotas públicas empermitAll(), o restoauthenticated() - RBAC:
@PreAuthorize("hasRole('ADMIN')")procura a authorityROLE_ADMIN - Esconder botão no frontend não é segurança: a regra que vale é a do backend
⚖️ Onde guardar o token
| Local | XSS | CSRF |
|---|---|---|
localStorage |
❌ lê | ✅ |
| Memória | 🟡 | ✅ |
Cookie HttpOnly + SameSite |
✅ | 🟡 |
⚠️ Armadilhas
- Aceitar
alg: none→ fixe o algoritmo esperado jwt.secretno repositório → variável de ambiente ou cofre- Token longo sem revogação → access curto + refresh com rotação
hasRole('ADMIN')com authority salva comoADMIN(semROLE_)
🗂️ No Catálogo
fullstack_estoque_02_spring_auth:JwtTokenProvider(HS256, 1 h),JwtAuthenticationFilter,SecurityConfig,@PreAuthorizenos controllers- Para melhorar no mesmo projeto: token em
localStorage, sem refresh token, segredo noapplication.properties
Slide 1 de 1
Atalhos: ← → Navegar • Espaço Avançar • F Tela Cheia • Home Início • End Fim