97 lines
5.8 KiB
Markdown
97 lines
5.8 KiB
Markdown
# 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).
|