ibanking-api-ai/standards/06-auth-2fa-flow.md

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).