A carteira na portaria
A portaria confere o documento e te dá um crachá. O crachá não é a lista do que você pode abrir — só diz que a portaria já te reconheceu. Perder o crachá no bolso da calça (cookie httpOnly) é diferente de grudá-lo na testa (localStorage).
Provar identidade sem entregar a chave
O atacante não precisa da senha se puder roubar ou forjar a prova de que o login já aconteceu.
Cookie legível por JS, token eterno e ausência de logout real transformam um XSS pontual em sequestro de conta.
Sessão server-side com id opaco: o valor no cookie não carrega claims; revogar é apagar a linha no store. JWT e afins deslocam estado para o cliente — útil em escala, mas a revogação e o lugar de armazenamento passam a ser o problema central.
SameSite mitiga CSRF em muitos fluxos; para cookies em APIs cross-site, anti-CSRF explícito ainda importa. Secure impede vazamento em HTTP claro.
Como isso aparece na prática
Login web clássico
Cenário
Um painel admin precisa de login com senha, logout imediato e sessão que expire ao fechar o expediente.
Como o padrão entra
Sessão no Redis, cookie httpOnly com maxAge de 8h, logout apaga a sessão no servidor.
Trade-off: Réplicas da API precisam do mesmo store de sessão — um cookie sticky sozinho não escala.
XSS que não rouba a sessão
Cenário
Uma biblioteca de analytics injeta script que lê document.cookie em páginas vulneráveis.
Como o padrão entra
Com httpOnly, o sid não aparece; o atacante ainda pode agir *pelo* browser da vítima, mas não extrai o cookie para outro dispositivo.
Trade-off: httpOnly não substitui corrigir XSS — só reduz o que o roubo consegue levar embora.
Onde isto dá errado
Token no localStorage
Qualquer XSS lê localStorage. Cookie httpOnly não é lido por JS; é o default que a maior parte dos apps web deveria usar.
Achar que login = permissão
Autenticado não significa admin. Autorização (roles, guards) é outro conceito — e outro lugar no código.
Sessão eterna sem revogação
Sem expiração e sem logout de verdade (só apagar cookie no cliente), um notebook perdido continua autenticado para sempre.
Sessão com cookie httpOnly
// Sessao no servidor + cookie httpOnly. O browser guarda o id;
// o JS da pagina NAO le o cookie — XSS nao rouba a sessao assim.
app.post("/login", async (req, res) => {
const user = await usuarios.autenticar(req.body.email, req.body.senha);
if (!user) return res.status(401).json({ erro: "credenciais invalidas" });
const sessao = await sessoes.criar(user.id); // id opaco no Redis/DB
res.cookie("sid", sessao.id, {
httpOnly: true, // inacessivel a document.cookie
secure: true, // so HTTPS
sameSite: "lax", // mitiga CSRF em navegacao cross-site
path: "/",
maxAge: 60 * 60 * 8,
});
res.json({ ok: true });
});
// Em cada request: le o cookie, resolve a sessao, anexa o user.
app.use(async (req, _res, next) => {
const sid = req.cookies.sid;
req.user = sid ? await sessoes.resolver(sid) : null;
next();
});Quando usar × quando evitar
Use quando
2- Apps e APIs que precisam saber quem está pedindo.
- Quando logout e revogação importam (painel, conta bancária, admin).
Evite quando
2- Recursos públicos sem identidade.
- Como único controle de acesso a ações privilegiadas.
Testar o que ficou
3 armadilhas de Autenticação viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.
Onde isto aparece de verdade
Você já usa isto, talvez sem saber o nome.
cookie de sessão httpOnlyO browser manda o id de sessão; o JS da página não consegue ler o cookie.Passport / NextAuth / Auth.jsBibliotecas que encapsulam estratégias de login e a emissão da sessão.middleware que anexa req.userDepois do login, cada request resolve a sessão e sabe quem está pedindo.
O padrão em uma linha
Sem nome de domínio, sem cerimônia. Só a ideia.
// Prova de identidade: sessão + cookie que o JS não lê.
res.cookie("sid", id, { httpOnly: true, secure: true, sameSite: "lax" });O que ele cobra
1 salto a mais entre a chamada e o efeito.
- Estado de sessão no servidor (ou store compartilhado) para cada usuário autenticado
- Cookies exigem cuidado com CSRF; tokens no cliente exigem cuidado com XSS — não há desenho de graça
Não vale se: o recurso é público de verdade e não há identidade a provar — autenticar aí só cria atrito e superfície de ataque.
Costuma ser confundido com
Onde isto aparece
Continue por aqui
- JWTJSON Web Token é um formato de credencial assinada: o servidor (ou o IdP) embute claims e uma assinatura, e quem recebe verifica sem necessariamente consultar um store de sessão. Útil para APIs e SSO — perigoso quando vira “auth completo” com token eterno no localStorage, algoritmo `none`, ou sem plano de refresh e revogação.
- OAuth 2.0OAuth 2.0 é delegação de acesso: um cliente obtém autorização para agir em nome do usuário sem ver a senha dele. O fluxo moderno é Authorization Code com PKCE; o implícito morreu. OIDC acrescenta identidade (id_token) em cima. Inventar “OAuth caseiro” com senha no body de um SPA costuma ser pior que sessão clássica bem feita.
- Autorização (RBAC e guards)Autorização responde *o que você pode fazer* depois de autenticado. RBAC (roles) e guards/middleware — Nest guards, Next middleware, Express — concentram a decisão perto da rota ou do caso de uso. “Tem `req.user`” não é autorização; IDOR e checagem só no front são as falhas clássicas.
- MFA / 2FAAutenticação multifator exige mais de uma prova independente — tipicamente algo que você sabe (senha) e algo que você tem (TOTP, chave de segurança). MFA reduz conta tomada por senha vazada; não impede XSS em sessão já aberta, phishing bem feito contra códigos, nem falhas de autorização. Backup codes e recuperação são parte do desenho, não um pós-escrito.
- Rate limitingCapacidade é finita, e demanda não pede licença. Limitar a taxa é escolher conscientemente quem é recusado quando a demanda passa do que se aguenta — em vez de deixar a sobrecarga escolher, degradando o serviço para todo mundo ao mesmo tempo.