Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Cookies Seguros no Node.js

Atualizado em: 5 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Cookies são usados para sessões, preferências e tokens de renovação em aplicações Node.js. Como o navegador os envia automaticamente, uma configuração incorreta pode expor credenciais a JavaScript malicioso, conexões sem TLS, subdomínios comprometidos e ataques CSRF.

Cookies seguros exigem atributos corretos, escopo mínimo, rotação de sessão, expiração, validação no servidor e uma política clara para ambientes diferentes.

res.cookie('__Host-session', sessionId, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  path: '/',
  maxAge: 1000 * 60 * 60 * 8,
});

O prefixo __Host- exige Secure, Path=/ e ausência de Domain em navegadores compatíveis. Isso reduz interferência de subdomínios.

HttpOnly

HttpOnly impede leitura direta por document.cookie. Ele reduz roubo de sessão por XSS, mas não impede que um script malicioso faça requisições usando o cookie. Por isso, CSP, sanitização e proteção CSRF continuam necessárias.

Secure

Secure limita o envio a HTTPS. Em produção, nunca envie sessão por HTTP. Quando TLS termina no proxy, configure trust proxy corretamente:

app.set('trust proxy', 1);

Não confie em qualquer proxy sem conhecer a topologia, pois isso afeta protocolo, IP e cookies.

SameSite

  • Strict: mais restritivo, pode afetar navegação iniciada por links externos;
  • Lax: equilíbrio comum para sessões web;
  • None: permite cross-site e exige Secure.

Aplicações com frontend e API em sites diferentes podem precisar de None. Nesse cenário, implemente CSRF explicitamente.

Domain

Omitir Domain cria um cookie host-only, enviado apenas ao host que o definiu. Use Domain=.example.com somente quando vários subdomínios realmente precisam compartilhar a credencial.

Um subdomínio vulnerável pode ampliar o impacto de cookies compartilhados.

Path

Path reduz onde o navegador envia o cookie:

res.cookie('__Secure-refresh', refreshToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  path: '/auth/refresh',
});

Path não é uma barreira de segurança completa entre aplicações do mesmo host, mas reduz exposição desnecessária.

Expires e Max-Age

Max-Age define duração relativa; Expires, uma data absoluta. Cookies sem ambos são de sessão do navegador, embora navegadores possam restaurar sessões.

O servidor deve validar expiração independentemente do navegador. Um cookie antigo não deve reativar uma sessão removida.

Assinatura detecta alteração do valor, mas não o criptografa:

import cookieParser from 'cookie-parser';

app.use(cookieParser(process.env.COOKIE_SIGNING_SECRET));

res.cookie('preferences', JSON.stringify({ theme: 'dark' }), {
  signed: true,
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
});

Não coloque dados sensíveis em cookies apenas assinados. O usuário ainda pode ver o conteúdo.

Sessão opaca

Uma abordagem robusta é armazenar no cookie apenas um ID aleatório e manter dados da sessão no servidor:

const sessionId = crypto.randomBytes(32).toString('base64url');
await sessions.set(sessionId, {
  userId: user.id,
  createdAt: Date.now(),
}, { ttlSeconds: 28800 });

Hash do ID pode ser armazenado para reduzir impacto de vazamento do banco.

JWT em cookie continua sendo enviado automaticamente e pode sofrer CSRF. Além disso, revogação e rotação exigem planejamento. Se usar, mantenha validade curta, claims mínimas, assinatura forte e estratégia para logout.

Refresh token

Refresh tokens devem ser longos, aleatórios, rotacionados e armazenados de forma que possam ser revogados. Um cookie HttpOnly reduz exposição a JavaScript, mas a rota de refresh precisa de SameSite, validação de origem e proteção contra replay.

Rotação de sessão

Regere o identificador depois de login, MFA, elevação de privilégio e troca de senha:

await sessionStore.destroy(oldSessionId);
const newSessionId = createSessionId();
await sessionStore.create(newSessionId, sessionData);

Isso reduz session fixation.

Logout

Remova a sessão no servidor e limpe o cookie usando os mesmos atributos principais:

await sessions.delete(sessionId);
res.clearCookie('__Host-session', {
  secure: true,
  sameSite: 'lax',
  path: '/',
});

Limpar somente no navegador não revoga uma credencial copiada.

Cookies e cache

Respostas personalizadas não devem ser armazenadas em cache público. Configure:

res.set('Cache-Control', 'private, no-store');

Evite incluir Set-Cookie em respostas cacheadas por CDN sem regras específicas.

Limites de tamanho

Cookies são enviados em muitas requisições. Valores grandes aumentam banda e podem ultrapassar limites de servidor ou proxy. Guarde somente identificadores e informações mínimas.

Múltiplos aplicativos no mesmo domínio

Use nomes exclusivos, host-only e paths adequados. Dois sistemas usando session podem sobrescrever ou interpretar valores incorretos.

Ambiente local

Não desative Secure silenciosamente em qualquer ambiente. Crie configuração explícita e garanta que produção falhe se HTTPS não estiver habilitado.

const isProduction = process.env.NODE_ENV === 'production';

if (isProduction && process.env.COOKIE_SECURE !== 'true') {
  throw new Error('Cookies seguros são obrigatórios em produção');
}

Prefixos __Secure- e __Host-

__Secure- exige Secure. __Host- é mais restritivo e impede Domain. Prefira __Host- para sessão principal quando o escopo permitir.

CHIPS e Partitioned

Cookies particionados podem ser usados em certos cenários de terceiros. O suporte e a semântica devem ser verificados nos navegadores-alvo. Não use para contornar políticas de privacidade sem uma necessidade legítima.

Logs

Nunca registre o header Cookie, Set-Cookie, IDs de sessão ou refresh tokens. Configure redaction:

const logger = pino({
  redact: [
    'req.headers.cookie',
    'res.headers.set-cookie',
  ],
});

Testes

const response = await request(app).post('/login').send(credentials);
const cookie = response.headers['set-cookie'][0];

expect(cookie).toContain('HttpOnly');
expect(cookie).toContain('Secure');
expect(cookie).toContain('SameSite=Lax');
expect(cookie).toContain('Path=/');

Teste logout, expiração, rotação, proxy e requisições cross-site.

Erros comuns

  • armazenar senha ou dados pessoais no cookie;
  • usar Domain amplo sem necessidade;
  • esquecer Secure em produção;
  • considerar HttpOnly proteção completa contra XSS;
  • usar SameSite=None sem CSRF;
  • não revogar sessão no servidor;
  • registrar Cookie ou Set-Cookie;
  • manter sessões indefinidamente;
  • usar valor previsível;
  • não rotacionar após login.

Fluxo recomendado

  1. use ID aleatório e opaco;
  2. prefira cookie host-only;
  3. ative HttpOnly e Secure;
  4. escolha SameSite conscientemente;
  5. defina Path e expiração;
  6. rotacione sessão;
  7. revogue no logout;
  8. proteja contra CSRF;
  9. redija logs;
  10. teste no proxy real.

Combine cookies seguros com CSRF no Node.js, CORS, TLS e HTTPS, Pino e Secret Management.

Consulte a documentação de Set-Cookie da MDN e o guia de sessões da OWASP.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita