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

# Autenticación

> Flujo de inicio de sesión, sesiones persistentes, idle timeout y refresh tokens

## Inicio de sesión

Los usuarios inician sesión en `admin.woku.app/login` con su email (o
usuario) + contraseña. La contraseña se compara contra un hash
bcrypt; la contraseña en plano nunca se almacena ni se transmite más
allá del propio formulario.

Un inicio de sesión exitoso genera:

* Un **access token** (JWT firmado) que el cliente adjunta como
  `Authorization: Bearer <token>` en cada request.
* Un **refresh token** opaco (32 bytes aleatorios, single-use) con
  validez de 30 días.
* Una **Session** persistida del lado del servidor que liga el token
  a un usuario y permite revocarlo o expirarlo.

## Idle timeout

Cada request autenticado refresca el campo `lastActivity` de la
sesión (debounced cada 60 segundos para no saturar la base). Si la
sesión queda sin actividad por más del tiempo configurado, se cierra
automáticamente: el siguiente request recibe `401 Unauthorized` y el
usuario debe iniciar sesión de nuevo.

* **Default**: 30 minutos de inactividad → cierre.
* **Override per-sesión**: opcional, vía el campo `idleTimeoutMin` de
  la sesión.
* **Override global**: variable de entorno `SESSION_IDLE_TIMEOUT_MIN`.

El cierre por idle también persiste `isClosed: true` en la sesión, de
modo que un atacante con el token robado tampoco puede usarlo.

## Refresh tokens (rotación single-use)

Cuando el cliente quiere prolongar la sesión sin pedirle al usuario
que ingrese sus credenciales nuevamente, envía su refresh token actual
al servicio de autenticación. El servidor:

1. Verifica que el refresh exista, no esté cerrado, y no esté
   vencido.
2. Genera **un nuevo par** (access + refresh) y **invalida el viejo**
   atómicamente en la misma fila `Session`.
3. Devuelve el par nuevo.

Si el refresh es desconocido, está cerrado, o ya expiró, la respuesta
es `401 Unauthorized` y el usuario debe iniciar sesión otra vez.

## Logout

Al cerrar sesión, esta se marca como cerrada (`isClosed: true`). A
partir de ahí, ningún request con ese access ni con su refresh
funciona.

## Garantías

* **Tokens nunca aparecen en la URL**: solo van por header o body, y
  TLS los protege en tránsito (ver [Headers y CSP](/seguridad/headers-y-csp)
  para HSTS).
* **Revocación inmediata**: el admin puede revocar cualquier sesión
  desde el endpoint backoffice; el siguiente request del token
  revocado falla.
* **Compatibilidad**: el flujo con solo access token sigue
  funcionando para clientes que no implementan refresh (la rotación
  es opt-in).
