¿Qué hace Seguridad de Autenticación?
Reglas
- Hash de contraseñas con bcrypt (factor de costo 12+) o argon2id — nunca almacenar en texto plano o usar SHA/MD5
- Limitar la tasa de puntos finales de inicio de sesión: máximo 5 intentos por minuto por IP, 10 por cuenta por hora
- Implementar bloqueo exponencial: 1s, 2s, 4s, 8s... después de intentos fallidos, bloqueo duro a los 10 fallos durante 15 min
- Los tokens de restablecimiento de contraseña: criptográficamente aleatorios, de un solo uso, expiran en 1 hora como máximo
- Devolver errores genéricos: "Correo electrónico o contraseña inválidos" — nunca revelar qué campo es incorrecto
- Exigir una longitud mínima de contraseña de 8 caracteres, verificar contra listas de contraseñas filtradas (API de HaveIBeenPwned)
import bcrypt from "bcrypt";
const hash = await bcrypt.hash(password, 12);
const valid = await bcrypt.compare(password, storedHash);
if (!valid) {
await incrementFailedAttempts(userId);
return res.status(401).json({ error: "Correo electrónico o contraseña inválidos" });
}
await resetFailedAttempts(userId);
async function checkLockout(userId: string) {
const attempts = await getFailedAttempts(userId);
if (attempts.count >= 10) {
const lockoutEnd = attempts.lastAttempt + 15 * 60 * 1000;
if (Date.now() < lockoutEnd) throw new Error("Cuenta temporalmente bloqueada");
}
}
Evitar
- Almacenar contraseñas en texto plano, base64 o cifrado reversible
- SHA-256 para contraseñas — es rápido, lo que significa que se puede forzar por fuerza bruta
- Revelar si un correo electrónico existe durante el inicio de sesión o el restablecimiento de contraseña
- Enlaces de restablecimiento de contraseña que nunca expiran o que se pueden reutilizar
- Permitir intentos de inicio de sesión ilimitados desde una sola IP