Autenticación de dos factores y seguridad de contraseñas
Has construido una aplicación web y los usuarios se están registrando. Pero, ¿están realmente seguras sus cuentas? Las contraseñas débiles y la falta de autenticación de dos factores (2FA) se encuentran entre las formas más fáciles para que los atacantes accedan. En esta guía, repasaremos prácticas recomendadas, prácticas y atemporales, para la seguridad de contraseñas y 2FA que puedes implementar hoy mismo.
Por qué la seguridad de contraseñas sigue siendo importante
A pesar de años de advertencias, las contraseñas siguen siendo el método de autenticación principal para la mayoría de las aplicaciones web. Los atacantes lo saben y atacan las contraseñas mediante phishing, credential stuffing y fuerza bruta. Una sola contraseña comprometida puede provocar la toma de control de la cuenta, robo de datos y daño reputacional.
Las políticas de contraseñas seguras y 2FA elevan significativamente el listón para los atacantes. Veamos cómo hacer ambas cosas correctamente.
Almacenamiento de contraseñas: hashing bien hecho
Nunca almacenes contraseñas en texto plano. Siempre aplícales hash con un algoritmo fuerte y lento diseñado para contraseñas. Los hashes rápidos como SHA-256 no son adecuados porque permiten ataques de fuerza bruta rápidos.
Algoritmos recomendados:
- Argon2id – Ganador del Password Hashing Competition, resistente a ataques de GPU y de canal lateral.
- bcrypt – Ampliamente soportado, probado en batalla y lento por diseño.
- scrypt – Memory-hard, bueno para prevenir ataques acelerados por hardware.
Ejemplo usando bcrypt en Node.js:
const bcrypt = require('bcrypt');
const saltRounds = 12;
async function hashPassword(password) {
return await bcrypt.hash(password, saltRounds);
}
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
Siempre usa una sal única por contraseña (la mayoría de las librerías lo manejan automáticamente). Ajusta el factor de coste para que el hashing tarde ~100-500ms en tu servidor.
Políticas de contraseñas que realmente ayudan
Olvida reglas complejas como "debe incluir un símbolo y un número". La guía moderna (NIST SP 800-63B) recomienda:
- Longitud mínima de 8 caracteres, pero fomentar frases de contraseña (p. ej., 4+ palabras aleatorias).
- Verificar contra listas de contraseñas filtradas (p. ej., API Have I Been Pwned).
- Sin caducidad periódica forzada a menos que se sospeche compromiso.
- Permitir todos los caracteres ASCII imprimibles y espacios.
- Limitar la tasa de intentos de inicio de sesión para prevenir fuerza bruta.
Implementa un medidor de fortaleza simple que dé retroalimentación sin bloquear contraseñas legítimas.
Métodos de autenticación de dos factores (2FA)
2FA añade un segundo factor: algo que tienes (teléfono, llave de hardware) o algo que eres (biometría). Aquí tienes métodos comunes, ordenados por seguridad:
| Método | Seguridad | Usabilidad |
|---|---|---|
| Llaves de seguridad hardware (WebAuthn/FIDO2) | Alta | Media |
| Aplicaciones de autenticación (TOTP) | Alta | Alta |
| Notificaciones push | Media | Alta |
| Códigos SMS | Baja | Alta |
El SMS es vulnerable al SIM swapping y a la interceptación. Prefiere TOTP o WebAuthn cuando sea posible.
Implementación de 2FA basada en TOTP
TOTP (contraseña de un solo uso basada en tiempo) es un gran equilibrio entre seguridad y usabilidad. Aquí tienes un flujo de trabajo de alto nivel:
- Genera una clave secreta para el usuario (p. ej., 32 bytes aleatorios, codificados en base32).
- Crea una URI otpauth:// y muestra un código QR para que el usuario lo escanee con una aplicación de autenticación.
- Verifica que el usuario pueda generar un código válido antes de habilitar 2FA.
- Almacena el secreto de forma segura (cifrado en reposo).
- Proporciona códigos de respaldo para la recuperación de la cuenta.
Durante el inicio de sesión, después de verificar la contraseña, solicita el código TOTP. Verifícalo con una librería como otplib o speakeasy.
const { authenticator } = require('otplib');
// Generar secreto
const secret = authenticator.generateSecret();
// Verificar token
const isValid = authenticator.verify({ token: userToken, secret });
Permite una pequeña ventana de tiempo (p. ej., ±1 intervalo) para tener en cuenta la deriva del reloj.
WebAuthn: el futuro de la autenticación
WebAuthn (parte de FIDO2) permite la autenticación sin contraseña y como segundo factor usando llaves de hardware o autenticadores de plataforma (Touch ID, Windows Hello). Es resistente al phishing porque la credencial está vinculada al origen.
Implementar WebAuthn requiere:
- Generación y verificación de desafíos en el servidor.
- JavaScript en el cliente usando la API WebAuthn.
- Almacenar claves públicas e IDs de credenciales para cada usuario.
Librerías como SimpleWebAuthn lo facilitan. Aunque es más complejo que TOTP, WebAuthn ofrece la protección más fuerte.
Limitación de tasa y bloqueo de cuentas
Incluso con 2FA, debes prevenir ataques de fuerza bruta en las contraseñas. Implementa:
- Limitación de tasa por IP y por cuenta (p. ej., 5 intentos por minuto).
- Retroceso exponencial tras intentos fallidos.
- Bloqueo de cuenta tras fallos repetidos, con un proceso de desbloqueo seguro (p. ej., verificación por correo electrónico).
- CAPTCHA tras unos pocos fallos.
Ten cuidado de no bloquear permanentemente a usuarios legítimos; usa bloqueos temporales y notifica al usuario.
Restablecimiento seguro de contraseña
Los flujos de restablecimiento de contraseña son un vector de ataque común. Sigue estas reglas:
- Usa un token de un solo uso y con tiempo limitado enviado por correo electrónico.
- No reveles si un correo electrónico existe en el sistema.
- Requiere que el usuario se reautentique si ya ha iniciado sesión.
- Invalida todas las sesiones después de un restablecimiento de contraseña.
Educar a los usuarios sin culparlos
La seguridad es una responsabilidad compartida. Proporciona una guía clara:
- Usa un gestor de contraseñas para generar y almacenar contraseñas únicas.
- Habilita 2FA siempre que sea posible.
- Desconfía de los intentos de phishing.
Los consejos dentro de la aplicación y una página de seguridad dedicada pueden ayudar.
Preguntas frecuentes
¿Es mejor el 2FA por SMS que no tener 2FA?
Sí, el 2FA por SMS es mejor que nada, pero es vulnerable al SIM swapping y a la interceptación. Prefiere TOTP o WebAuthn para una seguridad más fuerte.
¿Con qué frecuencia debo rotar los algoritmos de hashing de contraseñas?
No necesitas rotar a menos que se encuentre una vulnerabilidad. Sin embargo, puedes aplicar rehash a las contraseñas en el inicio de sesión exitoso cuando actualices parámetros (p. ej., aumentar el coste de bcrypt).
¿Puedo usar 2FA con OAuth o inicio de sesión social?
Sí, pero 2FA normalmente lo gestiona el proveedor de identidad. Si usas inicio de sesión social, asegúrate de que tu propio proceso de recuperación de cuenta sea seguro.
¿Listo para mejorar la seguridad de tu aplicación? Comienza implementando un hashing de contraseñas fuerte y 2FA basado en TOTP hoy mismo. Para más herramientas de desarrollo, consulta nuestro JSON Formatter para depurar respuestas de API rápidamente.