# 06 — Flujo de Autenticación con Doble Factor (2FA / OTP) ## Contrato de negocio y reglas de seguridad para el inicio de sesión seguro > **Propósito:** Esta guía define las reglas de negocio estrictas, los límites de intentos, la validación de campos y el flujo de estados necesarios para implementar el inicio de sesión seguro con Segundo Factor de Autenticación (M2FA / SoftToken). --- ## 1. El Flujo de Estados del Login 2FA El proceso de autenticación consta de dos fases transaccionales para evitar la exposición de credenciales y asegurar que solo dispositivos autorizados completen el acceso. ``` [POST /api/auth/login] (userName, password, softToken?) │ ┌─────────────┴─────────────┐ ▼ ▼ (Sin SoftToken) (Con SoftToken) ¿Requiere 2FA? ¿Token Válido? ┌───────┴───────┐ ┌───────┴───────┐ ▼ ▼ ▼ ▼ [SÍ] [NO] [SÍ] [NO] Retornar 2FA Login Exitoso Establecer Incrementar Requerido (401) Establecer Cookies JWT Intento 2FA Cookies JWT y retornar OK (Máx 3) ``` --- ## 2. Reglas de Validación de Entrada Antes de realizar la llamada al servicio de autenticación, el Route Handler local de Next.js debe validar estrictamente los campos en el servidor: ### 2.1 Nombre de Usuario (`userName`): - **Obligatoriedad:** Requerido. Si está vacío: retornar código `USERNAME_REQUIRED` con el mensaje: `"Este campo es obligatorio"` (Status `400`). - **Longitud Mínima:** 6 caracteres. Si es menor: retornar código `USERNAME_TOO_SHORT` con el mensaje: `"Debe ser mayor o igual a seis caracteres"` (Status `400`). - **Longitud Máxima:** 12 caracteres. Si es mayor: retornar código `USERNAME_TOO_LONG` con el mensaje: `"El sistema solo debe permitir ingresar 12 caracteres"` (Status `400`). ### 2.2 Contraseña (`password`): - **Obligatoriedad:** Requerido. Si está vacío: retornar código `PASSWORD_REQUIRED` con el mensaje: `"Este campo es obligatorio"` (Status `400`). ### 2.3 Código OTP / SoftToken (`softToken`): - **Obligatoriedad:** Requerido únicamente en la segunda fase del flujo (cuando se envía junto al usuario y clave). Si está vacío en la fase 2: retornar código `TOKEN_REQUIRED` con el mensaje: `"Este campo es obligatorio"` (Status `400`). --- ## 3. Control de Intentos y Bloqueos de Usuario Para proteger el sistema contra ataques de fuerza bruta, el Route Handler debe llevar un control estricto de intentos fallidos en memoria y aplicar las siguientes penalizaciones: ### 3.1 Control de Intentos de Contraseña (Fase 1) - **Límite Máximo:** 3 intentos fallidos de clave. - **Acción al llegar al límite:** El estado del usuario pasa a **`suspendido`**. - **Mensaje de Error:** - Intentos < 3: `"Usuario o Clave Inválida"` (Status `401`). - Intentos = 3: `"Tu usuario ha sido suspendido. Ingresa en la opción Autogestión de Usuario"` (Status `403`). ### 3.2 Control de Intentos de Código OTP / SoftToken (Fase 2) - **Límite Máximo:** 3 intentos fallidos de token. - **Acción al llegar al límite:** El estado del usuario pasa a **`bloqueado`** de forma definitiva en la base de datos y se dispara la alerta de seguridad interna. - **Mensajes de Error por Intento:** - **1er Intento Fallido:** `"Código inválido"` (Status `400`). - **2do Intento Fallido:** `"Código inválido, al tercer intento tu usuario será bloqueado"` (Status `400`). - **3er Intento Fallido (Bloqueo):** `"Código inválido, tu usuario ha sido bloqueado. Por favor ingresa a la opción Autogestión de Usuario"` (Status `403`). --- ## 4. Control de Doble Sesión Activa (`ACTIVE_SESSION`) Antes de procesar las credenciales en el backend, el sistema verificará si el usuario ya tiene una sesión web activa en otro navegador. - **Validación:** Comparar el `x-session-id` del request con las sesiones registradas en memoria. - **Acción si está activo en otra sesión:** Denegar el login y retornar el mensaje: - `"Usuario activo en otra sesión. Por tu seguridad cierra la sesión y vuelve a ingresar tu usuario"` (Status `403`). --- ## 5. Estados de Cuenta del Usuario El backend retornará el estado de cuenta (`status` / `accountStatus`) tras procesar las credenciales. Next.js debe denegar el acceso inmediatamente si el estado no es `"activo"`: | Estado de Cuenta | Acción en Next.js | Mensaje a Retornar al Cliente | Status HTTP | |---|---|---|---| | `bloqueado` | Denegar Acceso | *"Tu usuario se encuentra bloqueado. Ingresa en la opción Autogestión de Usuario"* (Si es Master: *"Usuario bloqueado. Por favor comunícate con Soporte Exterior Empresas a través del (0212-501.5500)"*) | `403` | | `suspendido` | Denegar Acceso | *"Tu usuario ha sido suspendido. Ingresa en la opción Autogestión de Usuario"* | `403` | | `inactivo` | Denegar Acceso | *"Usuario inactivo. Por favor comunícate con Soporte Empresas a través del (0212-501.5500)"* | `403` | | `reiniciado` | Denegar Acceso | *"Por favor ingresa a la opción Autogestión de Usuario"* | `403` | --- ## 6. Manejo Exitoso y Establecimiento de Cookies Una vez superadas las credenciales y el código 2FA de forma exitosa: 1. **Resetear Contadores:** Poner a `0` los intentos de contraseña y token de ese usuario. 2. **Establecer Cookies HTTP-only:** - **`access_token`:** Token de acceso de corta duración (con flag `httpOnly`, `secure: true` en prod, `sameSite: 'strict'`, y su `maxAge` provisto por el backend). - **`refresh_token`:** Token de refresco de larga duración (configurado con las mismas flags y `maxAge` de 7 días).