Sin Estado (Statelessness)

Fundamentos Security Notes Jan 6, 2025 JAVASCRIPT

Definicion

Cada vez que entras a una sucursal bancaria, muestras tu identificación. No esperas que el cajero te recuerde de la semana pasada y simplemente te entregue efectivo. Esto es statelessness en acción - cada interacción es completa y autocontenida, requiriendo que toda la información necesaria se presente nuevamente. En el diseño de APIs, statelessness significa que cada petición contiene todo lo necesario para procesarla, sin que el servidor recuerde nada entre peticiones.

Esto podría parecer ineficiente al principio. ¿Por qué deberías probar quién eres en cada petición? ¿Por qué el servidor no puede simplemente recordarte? La respuesta está en la escala y la fiabilidad. Cuando un servidor almacena información sobre cada cliente (llamado “estado”), queda atado a ese cliente específico. Si tienes millones de usuarios, almacenar estado para cada uno consume recursos masivos. Peor aún, si ese servidor falla, todo ese estado se pierde. Si necesitas agregar más servidores para manejar la carga, tienes que descubrir cómo compartir o sincronizar el estado entre ellos.

El diseño sin estado evita elegantemente estos problemas. Cualquier servidor puede manejar cualquier petición porque toda la información necesaria viene con la petición misma - usualmente en forma de un token. ¿Necesitas más capacidad? Solo agrega servidores. ¿Un servidor falla? Los otros servidores siguen funcionando. ¿Necesitas desplegar una actualización? Reinicia servidores uno por uno sin afectar a los usuarios. Por esto las APIs REST y la mayoría de servicios web modernos adoptan statelessness, aunque significa incluir información de autenticación con cada petición.

Ejemplo

APIs basadas en JWT: Cuando estás logueado en una aplicación web usando JWTs, tu navegador envía el token con cada petición a la API. El servidor no recuerda que iniciaste sesión hace cinco minutos - verifica tu token nuevamente cada vez. Si eliminas el token de tu navegador, es como si nunca hubieras iniciado sesión.

CDN y caching: Las Redes de Distribución de Contenido funcionan porque las peticiones son sin estado. Cuando solicitas una imagen, cualquier servidor CDN en el mundo puede servirla sin necesitar conocer tu historial. Por eso los sitios web cargan rápido sin importar dónde estés.

Servidores web con balanceo de carga: Sitios grandes como Netflix tienen miles de servidores. Tus peticiones podrían llegar a diferentes servidores cada vez, pero no importa - cada petición es autocontenida. Los servidores no necesitan compartir información sobre ti.

Funciones en la nube (AWS Lambda, etc.): La computación serverless solo es posible porque las peticiones son sin estado. Una nueva instancia de función se inicia, maneja tu petición, y desaparece. No hay dónde almacenar estado aunque quisieras.

Analogia

El Cajero Bancario Diferente: Cada vez que visitas el banco, podrías tener un cajero diferente. No esperas que conozcan los detalles de tu cuenta de memoria - presentas tu identificación, y ellos buscan lo que necesitan. Las APIs sin estado funcionan exactamente así: cada petición muestra su “identificación” (token), y el servidor busca lo que necesita.

La Cabina de Peaje: En una cabina de peaje, pagas por tu cruce. La cabina no recuerda que pagaste ayer o que eres un conductor frecuente. Cada cruce es una transacción completa y autocontenida. Las APIs sin estado tratan cada petición de la misma manera.

La Máquina Expendedora: Una máquina expendedora no tiene memoria de tus compras anteriores. Cada transacción requiere insertar dinero y hacer una selección. No sabe que compraste papas ayer o que vas por tu tercer refresco hoy. Cada interacción es independiente.

El Mostrador de Devoluciones de la Biblioteca: Cuando devuelves un libro de biblioteca, traes el libro y tu carnet. El bibliotecario no recuerda habértelo prestado - escanean todo nuevamente. Cada interacción incluye toda la información necesaria.

Code Example


// Peticiones sin estado - cada una incluye token de auth
GET /api/orders/456
Authorization: Bearer eyJhbGc...

GET /api/orders/789
Authorization: Bearer eyJhbGc...

// Con estado (anti-patrón en REST)
POST /api/login  // Servidor crea sesión
GET /api/orders/456  // Servidor recuerda que estás logueado
GET /api/orders/789  // Sigue recordando

// Diseño sin estado apropiado
const token = jwt.sign({ userId: 123 }, secret, { expiresIn: '1h' });
// Cliente incluye token en cada petición
headers: { 'Authorization': 'Bearer ' + token }

Notas de Seguridad

SECURITY NOTES
  • Las APIs sin estado deben usar tokens (JWT, OAuth) en lugar de sesiones del lado del servidor.
  • Los tokens deben estar firmados para prevenir manipulación, incluir tiempos de expiración, y transmitirse solo sobre HTTPS.
  • Implementa mecanismos de rotación y revocación de tokens..

Standards & RFCs