> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Protección contra fuerza bruta

> Bloqueo automático tras intentos fallidos, notificación al usuario y desbloqueo administrativo

Woku detecta y bloquea ataques de fuerza bruta sobre el login para
proteger las cuentas de los usuarios.

## Cómo funciona

1. Cada intento de login (exitoso o fallido) queda registrado en una
   tabla `LoginAttempt` con el identificador usado (lowercased), la
   IP de origen y el resultado.
2. Si una cuenta acumula **5 intentos fallidos en los últimos 15
   minutos**, el sistema:
   * Pone el campo `lockedUntil` del usuario a **15 minutos en el
     futuro**.
   * Registra una entrada `auth.lockout` en el [registro de
     auditoría](/seguridad/audit-log) con `failedAttempts`,
     `lockedUntil` y la IP del último intento.
   * Envía un **email** al usuario notificando el bloqueo (ver
     abajo).
3. Durante el bloqueo, cualquier intento de login (incluso con la
   contraseña correcta) responde `403 Forbidden`.
4. Pasado el window de 15 minutos, el bloqueo se levanta
   automáticamente al siguiente intento, no hace falta acción
   manual.

## Email de notificación

Cuando se dispara el bloqueo, el sistema envía al usuario un correo
vía AWS SES con:

* **Asunto**: "Bloqueo temporal de tu cuenta en woku".
* **Cuerpo**: explica que detectamos varios intentos fallidos,
  cuándo se levanta el bloqueo, desde qué IP, y un CTA para resetear
  la contraseña.

El email es **fire-and-forget**: si SES está caído, el bloqueo igual
ocurre y el fallo del correo se loguea internamente; no hay impacto
en la seguridad.

## Desbloqueo administrativo

Si el usuario necesita acceder antes de que pase el window, un
administrador interno puede desbloquearlo desde el backoffice. La
acción queda registrada como `auth.unlock` en el registro de
auditoría con la IP del request.

## Limitaciones

* La detección es **per-usuario**, no per-IP. Un atacante distribuido
  desde múltiples IPs probando muchos usuarios distintos no dispara
  el bloqueo por usuario, pero queda igualmente expuesto al rate
  limit global (10 req/s, 50 req/10s, 100 req/min por IP, gestionado
  por `@nestjs/throttler`).
* Si el atacante usa un identificador que no corresponde a ningún
  usuario, no hay bloqueo (no hay nada que bloquear), pero el rate
  limit por IP igual aplica.

## Verificación de estado

El estado de bloqueo de un usuario no se expone públicamente al
front. La UI muestra el mismo mensaje genérico ("Credenciales
inválidas o cuenta bloqueada") para evitar revelar si una cuenta
existe o no, esto reduce el riesgo de enumeración de usuarios.
