BookinglyTech News
Ciberseguridad

Cómo diseñar un login sin contraseña con SMS: OTP, cooldowns y límites de intentos

Guía práctica para modelar la autenticación por teléfono como una máquina de estados, evitando fugas de seguridad en la lógica de reenvío.

2 min de lecturaDev.to0 vistas

El artículo de Dev.to propone tratar el inicio de sesión sin contraseña mediante SMS no como dos handlers sueltos de Node.js o Express, sino como una máquina de estados persistente. La premisa es simple: primero verificar el control del número de teléfono y después enrutar la solicitud. Para mantener esto seguro, cooldowns, cuotas de envío, intentos máximos y consumo único deben vivir en un mismo registro duradero.

Cuatro relojes, una sola política

El autor desglosa la lógica en cuatro contadores independientes que no deben mezclarse en una sola variable: la expiración del OTP, el cooldown mínimo entre reenvíos, el límite de envíos en una ventana de tiempo y los fallos de verificación. Unirlos hace que el comportamiento en producción sea inexplicable.

Se proponen valores de configuración de ejemplo, no constantes universales: vida útil del código de 10 minutos, cooldown de 60 segundos, máximo cinco envíos por hora y cinco intentos de verificación fallidos por desafío activo. El punto crítico que resuelve vulnerabilidades comunes es que solicitar un nuevo código invalida el anterior pero no reinicia el presupuesto de intentos fallidos. Si se reseteara, un atacante podría alternar entre generar nuevos códigos y adivinar el hash indefinidamente.

La implementación de referencia usa Python 3.11 y SQLite para que la frontera transaccional sea visible, aunque la lógica de compare-and-update aplica a cualquier base de datos relacional o store que ofrezca escritura atómica condicional. El mensaje SMS debe ser corto, evitar texto controlado por el usuario y no pedir nunca una contraseña por respuesta.

El código incluye la normalización del teléfono al formato E.164 y el almacenamiento de un digest HMAC-SHA256 del código en lugar del código en claro. Esto permite verificar la identidad sin exponer el secreto durante el transporte o en reposo. El reenvío debe seguir una política acotada que rote el desafío sin otorgar nuevos permisos de conjetura.

No existe un valor universal honesto para estos parámetros; dependen del balance entre suprimir ráfagas de abuso y no frustrar al usuario por un SMS tardío o un doble clic. La recomendación es mantener estos ajustes en configuración externa y evaluarlos contra una suite de pruebas de abuso que cubra mensajes retrasados, dispositivos compartidos y tráfico a alta tasa antes de desplegarlos. Los límites de segmentación GSM-7 vs UCS-2 pueden alterar la entrega del mensaje, un detalle técnico que afecta directamente a la tasa de éxito de la autenticación.