Como implementar autenticação segura em aplicações web
1. Fundamentos da autenticação segura
A autenticação segura é o pilar central da proteção de aplicações web. Para implementá-la corretamente, é essencial compreender três princípios fundamentais: confidencialidade (dados acessíveis apenas a usuários autorizados), integridade (garantia de que os dados não foram alterados) e disponibilidade (sistema acessível quando necessário).
É crucial distinguir autenticação (verificar quem é o usuário), autorização (o que ele pode fazer) e identificação (como ele se apresenta ao sistema). As principais ameaças incluem ataques de força bruta, phishing e roubo de sessão, que exploram vulnerabilidades comuns em implementações mal projetadas.
2. Armazenamento seguro de senhas
Nunca armazene senhas em texto claro. Utilize algoritmos modernos de hashing como bcrypt, Argon2 ou scrypt, que são projetados para serem computacionalmente intensivos, dificultando ataques de força bruta.
// Exemplo de hashing com bcrypt em Node.js
const bcrypt = require('bcrypt');
const saltRounds = 12;
async function hashPassword(password) {
const salt = await bcrypt.genSalt(saltRounds);
const hash = await bcrypt.hash(password, salt);
return hash;
}
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
Adicione salt (valor aleatório único por senha) para proteger contra rainbow tables. Considere também um pepper (chave secreta armazenada no servidor) para camada extra de proteção. Implemente políticas de complexidade: mínimo 12 caracteres, combinação de maiúsculas, minúsculas, números e caracteres especiais.
3. Implementação de autenticação baseada em tokens
JWT (JSON Web Tokens) é amplamente utilizado para autenticação stateless. Um JWT consiste em header, payload e signature, permitindo verificar a integridade dos dados sem consultar o servidor.
// Exemplo de geração de JWT em Node.js
const jwt = require('jsonwebtoken');
function generateAccessToken(user) {
return jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
}
function generateRefreshToken(user) {
return jwt.sign(
{ userId: user.id },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: '7d' }
);
}
Utilize access tokens de curta duração (15-30 minutos) combinados com refresh tokens de longa duração (7-30 dias). Armazene tokens em cookies HttpOnly e Secure para proteção contra XSS. Evite localStorage, que é acessível via JavaScript.
4. Autenticação multifator (MFA)
MFA combina múltiplos fatores: algo que você sabe (senha), algo que você tem (dispositivo) e algo que você é (biometria). TOTP (Time-based One-Time Passwords) é uma implementação popular.
// Exemplo de implementação TOTP com speakeasy
const speakeasy = require('speakeasy');
function generateSecret() {
return speakeasy.generateSecret({ length: 20 });
}
function generateTOTP(secret) {
return speakeasy.totp({
secret: secret.base32,
encoding: 'base32'
});
}
function verifyTOTP(secret, token) {
return speakeasy.totp.verify({
secret: secret.base32,
encoding: 'base32',
token: token,
window: 1
});
}
Para maior segurança, implemente WebAuthn/FIDO2, que permite autenticação com chaves de segurança físicas ou biometria do dispositivo, eliminando completamente o risco de phishing.
5. Proteção contra ataques comuns
Proteja-se contra CSRF utilizando tokens sincronizadores ou cookies com atributo SameSite (Strict ou Lax). Para mitigar XSS, sanitize toda entrada do usuário e implemente Content Security Policy (CSP).
// Exemplo de middleware de rate limiting
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutos
max: 5, // 5 tentativas por janela
message: 'Muitas tentativas de login. Tente novamente em 15 minutos.',
standardHeaders: true,
legacyHeaders: false,
});
Implemente bloqueio temporário de contas após múltiplas falhas de autenticação e delays progressivos entre tentativas.
6. Gerenciamento de sessões e logout seguro
Sessões devem ser gerenciadas no lado do servidor com expiração automática. Para JWT, implemente uma lista de revogação (blacklist) para invalidar tokens antes do vencimento.
// Exemplo de logout em todos os dispositivos
async function logoutAllDevices(userId) {
// Incrementa versão do token do usuário
await User.findByIdAndUpdate(userId, {
$inc: { tokenVersion: 1 }
});
}
// Middleware de verificação de token
function verifyToken(req, res, next) {
const token = req.cookies.accessToken;
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Verifica se tokenVersion corresponde
if (decoded.tokenVersion !== user.tokenVersion) {
throw new Error('Token revogado');
}
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ error: 'Token inválido' });
}
}
7. Boas práticas de comunicação e infraestrutura
Force HTTPS em toda a aplicação e implemente HSTS para prevenir ataques man-in-the-middle. Configure headers de segurança essenciais:
// Exemplo de headers de segurança
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-XSS-Protection: 1; mode=block
Implemente logging detalhado de todas as tentativas de autenticação (bem-sucedidas e falhas) para auditoria e detecção de anomalias.
8. Estratégias de autenticação moderna e descentralizada
OAuth 2.0 e OpenID Connect permitem delegação de autenticação com provedores externos (Google, GitHub, etc.), reduzindo a responsabilidade de armazenar senhas.
// Exemplo de fluxo OAuth 2.0
// 1. Redirecionar usuário para provedor
https://accounts.google.com/o/oauth2/v2/auth?
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
response_type=code&
scope=openid%20profile%20email&
state=STATE_TOKEN
// 2. Receber código de autorização no callback
app.get('/auth/callback', async (req, res) => {
const { code } = req.query;
const tokens = await exchangeCodeForTokens(code);
// Criar sessão com tokens recebidos
});
Considere autenticação sem senha (passwordless) via magic links enviados por email ou WebAuthn, que oferece experiência superior e elimina riscos associados a senhas fracas. Para SSO, implemente federação de identidades usando SAML ou OpenID Connect, garantindo single sign-on seguro em múltiplas aplicações.
A implementação de autenticação segura exige atenção constante a cada detalhe, desde o armazenamento de credenciais até a infraestrutura de rede. Mantenha-se atualizado com as melhores práticas e revise regularmente sua implementação contra novas ameaças.
Referências
- OWASP Authentication Cheat Sheet — Guia oficial da OWASP com práticas recomendadas para implementação de autenticação segura.
- JSON Web Tokens Introduction — Documentação completa sobre estrutura, uso e implementação de JWT com exemplos interativos.
- bcrypt Documentation — Biblioteca oficial de hashing bcrypt para Node.js com exemplos de implementação.
- WebAuthn Guide - FIDO Alliance — Guia detalhado sobre autenticação sem senha usando WebAuthn e FIDO2.
- OAuth 2.0 Simplified — Tutorial prático sobre implementação de OAuth 2.0 com exemplos de fluxos de autorização.
- Mozilla Observatory — Ferramenta para testar headers de segurança e configuração HTTPS de sua aplicação.
- NIST Digital Identity Guidelines — Padrões oficiais do governo americano para implementação de identidade digital e autenticação.