Modelos stateful vs stateless: o que muda na arquitetura
Ao escolher entre sessão (stateful) e JWT (stateless), a diferença prática não é “qual é mais moderno”, e sim onde o estado de autenticação vive e como ele é verificado.
- Sessão (stateful): o servidor mantém um registro (estado) por usuário/dispositivo. O cliente carrega apenas um identificador (geralmente em cookie). A validação depende de consultar esse estado (memória, Redis, banco, etc.).
- JWT (stateless): o token carrega claims e é validado por assinatura. Em tese, o servidor não precisa consultar um armazenamento para validar cada requisição (embora, na prática, muitas arquiteturas adicionem checagens de revogação/risco).
Como este curso já cobriu fluxos, validação, refresh e proteções (CSRF/XSS etc.), aqui o foco é decisão arquitetural: critérios, trade-offs e padrões híbridos seguros.
Critérios de decisão: o que comparar antes de escolher
1) Revogação e controle de sessão
- Sessão: revogação tende a ser direta (invalidar o registro da sessão). Bom para “logout imediato”, bloqueio de conta, resposta a incidente e políticas de risco.
- JWT: revogação “pura” é difícil se você não mantém estado. Para revogar antes do expirar, você normalmente adiciona algum estado (denylist, versão de token, “token family”, etc.), o que reduz o ganho do stateless.
2) Escalabilidade e topologia
- Sessão: para escalar horizontalmente, você precisa de sticky sessions (acoplamento ao balanceador) ou session store compartilhado (Redis, banco). Isso é simples de operar, mas é um componente a mais.
- JWT: validação local (assinatura) é ótima para múltiplas instâncias e edge, e reduz dependência de store em cada request. Porém, a gestão de chaves, rotação e observabilidade de incidentes vira peça central.
3) Complexidade operacional
- Sessão: complexidade fica no servidor (store, expiração, limpeza, replicação). O cliente tende a ser simples.
- JWT: complexidade se espalha (cliente, gateway, serviços). Você precisa padronizar claims, audience/issuer, rotação de chaves, compatibilidade entre serviços e estratégia de expiração/renovação.
4) Superfície de ataque e impacto de vazamento
- Sessão: se um cookie de sessão vaza, o impacto é alto, mas você pode revogar rapidamente. A sessão pode ser atrelada a contexto (IP, device, risco) no servidor.
- JWT: se um access token vaza, ele pode ser usado até expirar (a menos que você tenha mecanismo de revogação/risco). Tokens tendem a circular mais (logs, headers, proxies) se não houver disciplina forte.
5) Observabilidade e auditoria de autenticação
- Sessão: por existir estado, é mais fácil registrar “sessão X criada, renovada, revogada” e correlacionar com eventos.
- JWT: você observa tokens em trânsito, mas não necessariamente “sessões” como entidade. Muitas equipes acabam criando um conceito de sessão mesmo com JWT (ex.: registro de device/session id) para auditoria e revogação.
Cenários comuns e recomendações práticas
SSR (Server-Side Rendering) tradicional
Perfil: páginas renderizadas no servidor, navegação via browser, cookies como mecanismo natural.
- Escolha frequente: sessão com cookie.
- Por quê: integração natural com browser, controle de revogação e menor necessidade de expor tokens a múltiplas camadas.
- Quando considerar JWT: se o SSR também atua como BFF (Backend for Frontend) e você precisa chamar APIs internas com identidade propagada, pode emitir um token curto para chamadas internas (padrão híbrido).
SPA (Single Page Application) consumindo API
Perfil: front separado, API JSON, CORS, múltiplas chamadas.
- Opção A (comum e segura): sessão em cookie + API protegida por cookie (com mitigação de CSRF já tratada em capítulo anterior). Vantagem: revogação simples e menos exposição de token em JS.
- Opção B: JWT (access token curto) + refresh token (conforme capítulo anterior). Vantagem: bom para múltiplos domínios/serviços e gateways; custo: mais complexidade e disciplina de armazenamento/renovação.
- Heurística: se você controla o mesmo domínio e quer simplicidade e revogação forte, sessão costuma ganhar; se você precisa de identidade propagada entre serviços e clientes diversos, JWT tende a ganhar.
Mobile (apps nativos)
Perfil: não depende de cookies do browser, precisa lidar com redes instáveis e múltiplos ambientes.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
- Escolha frequente: JWT (access curto + refresh) ou tokens opacos com introspecção.
- Por quê: o app gerencia headers facilmente; cookies não são tão naturais quanto no browser; e o ecossistema costuma exigir integração com múltiplos back-ends.
- Quando sessão faz sentido: se você tem um webview/fluxo híbrido e quer unificar com web, pode usar cookie, mas isso costuma aumentar complexidade no app.
APIs públicas (terceiros)
Perfil: clientes não confiáveis, integrações server-to-server, necessidade de revogar e limitar escopo.
- Escolha frequente: tokens (JWT ou opacos) com escopos e expiração curta; muitas vezes com gateway.
- Por quê: cookies não são adequados; você precisa de credenciais delegadas e rastreáveis por aplicação cliente.
- Nota: JWT pode ser útil para validação local em edge, mas tokens opacos com introspecção podem facilitar revogação e política centralizada.
Microserviços e comunicação serviço-a-serviço
Perfil: múltiplos serviços, necessidade de propagar identidade do usuário e/ou identidade do serviço.
- Escolha frequente: JWT curto para propagação de identidade (user/service) + políticas no gateway/mesh.
- Por quê: validação local reduz latência; claims padronizadas permitem autorização consistente.
- Risco: “JWT eterno” entre serviços vira credencial de alto impacto. Prefira tokens curtos, audience restrita e rotação de chaves.
Padrões híbridos seguros (quando “ou” vira “e”)
Padrão 1: JWT curto em cookie + proteção anti-CSRF
Ideia: usar JWT como access token, mas transportado em cookie (em vez de localStorage), reduzindo exposição a scripts e mantendo ergonomia do browser. Para evitar CSRF, você aplica uma estratégia anti-CSRF (já discutida anteriormente) e valida origem/headers conforme sua política.
Quando usar: SPA/SSR no mesmo domínio, necessidade de validação stateless em múltiplas instâncias, mas com preferência por cookie.
Trade-off: você ainda precisa lidar com renovação e revogação (muitas vezes com refresh token e/ou store de sessões).
Padrão 2: Sessão para web (browser) e JWT para serviços internos
Ideia: o usuário autentica via sessão no BFF/SSR. Quando o servidor precisa chamar microserviços, ele emite/obtém um JWT curto (ou token de serviço) para comunicação interna.
- Vantagem: browser fica simples e revogável; serviços ganham validação local e padronização.
- Cuidados: delimitar audience por serviço, expiração curta, e não “vazar” tokens internos para o cliente.
Padrão 3: Sessão “stateful” com token “stateless” (sessão como fonte de verdade)
Ideia: você emite JWT curto, mas mantém um registro de sessão/versão no servidor. A cada request, além de validar assinatura, você verifica se a sessão ainda é válida (ex.: versão, status, risco). Isso transforma o JWT em um cache de claims, não em fonte de verdade.
- Vantagem: revogação forte e claims rápidas.
- Custo: perde parte do benefício stateless (há consulta ao store), mas ganha controle.
Guia de decisão baseado em requisitos (checklist)
Use este guia como uma matriz de requisitos. Marque o que é “obrigatório” e veja qual abordagem atende com menor custo.
| Requisito | Sessão | JWT | Híbrido |
|---|---|---|---|
| Logout imediato e revogação forte | Excelente | Fraco sem estado adicional | Excelente |
| Escalar sem store compartilhado | Fraco (precisa store/sticky) | Excelente | Bom (depende do desenho) |
| Browser (SSR) simples e integrado | Excelente | Bom (mais peças) | Excelente |
| Clientes diversos (mobile, terceiros) | Fraco | Excelente | Excelente |
| Microserviços com validação local | Fraco | Excelente | Excelente |
| Menor complexidade inicial | Boa | Média/Alta | Alta |
| Menor impacto de vazamento (mitigável) | Bom (revoga fácil) | Depende (expiração curta ajuda) | Bom |
Passo a passo: como decidir em um projeto real
- Liste os clientes: browser SSR, SPA, mobile, parceiros, integrações internas.
- Defina requisitos não negociáveis: revogação imediata? SSO? multi-região? offline? auditoria por sessão?
- Mapeie o caminho do token/cookie: onde trafega (browser, gateway, CDN, logs), onde pode vazar, quem consegue ler.
- Escolha a “fonte de verdade”: estado no servidor (sessão) ou validade por assinatura (JWT). Se precisar de revogação forte, considere fonte de verdade stateful.
- Decida a estratégia de propagação: se há microserviços, como a identidade chega neles (JWT curto interno, token de serviço, etc.).
- Planeje rotação e incidentes: o que acontece se uma chave vazar? e se um token vazar? qual o tempo máximo de exposição aceitável?
- Documente a decisão (modelo abaixo) e valide com segurança/infra.
Como documentar a decisão (ADR enxuto)
Use um registro de decisão arquitetural (ADR) curto para evitar “decisões implícitas” que viram dívida técnica.
Modelo de ADR (copie e preencha)
ADR-00X: Estratégia de autenticação (Sessão vs JWT) Contexto: - Tipos de clientes: [SSR/SPA/Mobile/Terceiros] - Topologia: [monólito/microserviços/multi-região] - Requisitos: [revogação imediata, SSO, auditoria, latência, etc.] Decisão: - Para clientes web: [sessão em cookie | JWT em cookie | JWT em header] - Para mobile/terceiros: [JWT curto + refresh | token opaco] - Para serviço-a-serviço: [JWT curto com audience restrita | mTLS + identidade de serviço] Justificativas (trade-offs): - Revogação: ... - Escalabilidade: ... - Complexidade: ... - Superfície de ataque: ... Consequências: - Operação: [store de sessão, rotação de chaves, gateway, etc.] - Observabilidade: [eventos de sessão/token] - Plano de incidente: [revogar sessões, rotacionar chaves, etc.] Alternativas consideradas: - ... Referências internas: - Diagramas/links do repositórioExercício: escolha arquitetural para 3 aplicações
Para cada caso, escolha: (1) sessão, (2) JWT, ou (3) híbrido. Em seguida, escreva um mini-ADR com 5 a 10 linhas justificando pelos critérios (revogação, escalabilidade, complexidade, superfície de ataque).
Caso A: E-commerce com SSR + painel administrativo
- Clientes: browser (SSR), admin no mesmo domínio.
- Requisitos: logout imediato para admin, auditoria por sessão, picos sazonais, poucas integrações externas.
- Perguntas: você precisa propagar identidade para microserviços? há gateway? o admin exige revogação imediata?
Caso B: Fintech com SPA + app mobile + API para parceiros
- Clientes: SPA, iOS/Android, parceiros server-to-server.
- Requisitos: múltiplos clientes, expiração curta, resposta rápida a incidentes, integração com gateway, trilha de auditoria.
- Perguntas: você aceita estado central para revogação? como separar audiences e escopos por cliente?
Caso C: Plataforma B2B em microserviços multi-região
- Clientes: web (pode ser SSR ou SPA), muitos serviços internos, chamadas cross-region.
- Requisitos: baixa latência, validação local, rotação de chaves, isolamento por serviço, observabilidade.
- Perguntas: como limitar blast radius de um token? como garantir audience por serviço? precisa de sessão central para revogação?