Gestión de sesiones: cookies, tokens, timeouts y revocación

Cómo se construyen y defienden las sesiones web: atributos de cookie (HttpOnly, Secure, SameSite, Domain, Path), session tokens del lado servidor frente a JWTs y sus trade-offs, timeouts sliding frente a absolutos, idle timeout y re-autenticación forzada, cómo revocar realmente una sesión, y los controles contra CSRF, XSS y session hijacking.

La sesión es donde la autenticación sigue viva

La autenticación es un momento — el instante en que el usuario prueba quién es. Pero HTTP no tiene estado: sin ayuda, el servidor olvidaría esa prueba en la siguiente petición y pediría la contraseña de nuevo en cada clic. La sesión es el mecanismo que recuerda “este navegador ya se autenticó”, para que el usuario se pruebe una vez y siga reconocido.


Eso hace de la sesión uno de los activos más atacados de cualquier aplicación. Un ID de sesión válido es un portador de identidad autenticada: quien lo tenga es el usuario, sin contraseña. El artículo de SSO chocaba una y otra vez con esto — la sesión maestra del IdP, las sesiones de app independientes, por qué el logout es difícil. Este artículo abre esa caja: cómo se construyen las sesiones a partir de cookies y tokens, cuánto deben vivir, cómo terminarlas, y cómo defender la capa de los ataques que la apuntan.


Es un artículo técnico; espera atributos, headers y trade-offs concretos. La referencia canónica de campo es la OWASP Session Management Cheat Sheet, y encaja bien con todo lo de abajo.


Cookies: el contenedor y sus atributos

Para apps de navegador, la sesión casi siempre viaja en una cookie — un pequeño valor que el servidor fija y el navegador devuelve automáticamente en las peticiones siguientes. El valor en sí debe ser un identificador opaco de alta entropía. La seguridad está mayormente en los atributos que fijas junto a él. Omite uno y le das al atacante una palanca.

Set-Cookie: sid=9f2a...e71; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=1800
AtributoQué hacePor qué importa
HttpOnlyOculta la cookie de JavaScript (document.cookie)Un payload de XSS no puede leer el ID de sesión — el flag más importante
SecureEnvía la cookie solo por HTTPSEvita la intercepción del ID de sesión en texto claro
SameSiteControla la adjunción a peticiones cross-siteLa defensa principal contra CSRF a nivel de navegador
DomainQué hosts reciben la cookieUn dominio demasiado amplio filtra la cookie a subdominios que no deberían tenerla
PathQué rutas URL reciben la cookieAcota la cookie; un control menor, de defensa en profundidad
Max-Age / ExpiresVida de la cookieOmítelo para una cookie de sesión que muere con el navegador; fíjalo para persistencia

SameSite en detalle

SameSite es lo bastante sutil para merecer su propia nota porque es tu control de CSRF de primera línea:


  • Strict — la cookie nunca se envía en ninguna petición cross-site, ni siquiera navegación top-level. La más fuerte, pero significa que seguir un enlace desde un correo u otro sitio aterriza al usuario sin sesión, lo que puede dañar la UX.
  • Lax — la cookie se envía en navegaciones GET top-level (clic en un enlace) pero no en POSTs cross-site, iframes o peticiones en segundo plano. El default pragmático para cookies de sesión: bloquea el vector clásico de CSRF manteniendo la navegación normal.
  • None — la cookie se envía en todas las peticiones cross-site y debe ir con Secure. Úsalo solo cuando genuinamente necesites cookies cross-site (algunos flujos embebidos o federados), y compensa con tokens anti-CSRF.


Session tokens del lado servidor vs JWTs

Detrás de la cookie hay una elección que moldea todo sobre vida y revocación: ¿la sesión tiene estado (lado servidor) o no lo tiene (autocontenida)?


Session tokens del lado servidor (opacos)

La cookie contiene un ID aleatorio opaco que no significa nada por sí solo; es una llave al estado de sesión que el servidor guarda (en memoria, Redis, una base de datos). En cada petición el servidor busca el ID y lee la identidad, roles y metadatos asociados.


  • Pros: el servidor es la fuente de verdad. Puedes revocar al instante borrando el registro. Puedes guardar estado rico y cambiante. La cookie no filtra información si se intercepta (es solo una cadena aleatoria).
  • Contras: requiere un almacén del lado servidor y una búsqueda en cada petición; ese almacén debe escalar y compartirse entre instancias.

JWTs como sesiones (autocontenidos)

Un JWT es un token firmado y autodescriptivo que lleva los claims (subject, roles, expiración) dentro de él. El servidor valida la firma y lee los claims sin búsqueda — no se guarda nada del lado servidor.


  • Pros: sin estado y escalable horizontalmente; sin almacén de sesión; cómodo entre servicios y APIs (encaja con el mundo OAuth/OIDC del módulo de protocolos).
  • Contras: difícil de revocar. Como el servidor no guarda nada, no hay nada que borrar — un JWT robado es válido hasta que expire. Los claims también se vuelven obsoletos (un rol revocado a mitad de sesión sigue apareciendo en el token). Y un token más grande viaja en cada petición.

Token del lado servidorJWT
Fuente de verdadAlmacén del servidorEl token mismo
RevocaciónInstantánea (borrar registro)Difícil (esperar expiración / denylist)
EscalaNecesita almacén compartidoSin estado, fácil
Frescura del estadoSiempre actualPuede quedar obsoleto hasta reemitir
Mejor encajeApps web sensibles que necesitan controlAPIs/microservicios que necesitan escala


Vida: timeouts idle vs absolutos

Una sesión no debe vivir para siempre. Dos relojes independientes gobiernan cuánto dura, y los sistemas maduros corren ambos.

stateDiagram-v2
  accTitle: Ciclo de vida de una sesión web con timeouts idle y absoluto
  accDescr: Una sesión comienza anónima. Un login exitoso la mueve a activa. Desde activa, la inactividad la mueve hacia idle; cualquier petición la regresa a activa y reinicia el reloj idle. Alcanzar el idle timeout o el absolute timeout mueve la sesión a terminada. El logout o la revocación administrativa también la mueven a terminada desde activa. Desde terminada, la re-autenticación regresa al usuario a activa con una nueva sesión.
  [*] --> Anonima
  Anonima --> Activa: login (autenticar)
  Activa --> Activa: petición reinicia reloj idle
  Activa --> Idle: inactividad
  Idle --> Activa: petición antes del idle timeout
  Idle --> Terminada: idle timeout alcanzado
  Activa --> Terminada: absolute timeout alcanzado
  Activa --> Terminada: logout / revocada
  Terminada --> Activa: re-autenticar (nueva sesión)
  Terminada --> [*]
El ciclo de vida de la sesión. El login lleva al usuario de anónimo a activo. La inactividad desliza hacia el borde del idle timeout; cualquier petición lo reinicia a activo. Dos cosas terminan la sesión: alcanzar el idle timeout, o llegar al absolute timeout que limita la vida total desde el login. El logout o una acción administrativa pueden revocarla en cualquier punto. Una sesión terminada fuerza re-autenticación para iniciar una nueva.

  • Idle timeout (sliding) — termina la sesión tras un periodo de inactividad, y se reinicia en cada petición. Un usuario trabajando activamente nunca se interrumpe; una sesión dejada abierta en una máquina desatendida muere sola. Los valores típicos van de unos minutos para apps sensibles a decenas de minutos para las ordinarias.
  • Absolute timeout — termina la sesión un tiempo fijo después del login, sin importar cuán activo esté el usuario. Limita la vida total y fuerza re-autenticación periódica, para que incluso una sesión usada (o robada) de forma continua no pueda vivir indefinidamente. Los valores típicos van en horas para apps web, más cortos para contextos privilegiados.

Úsalos juntos: un idle corto atrapa el abandono, un tope absoluto más largo fuerza una prueba fresca de identidad con un calendario. Y más allá de los timeouts, fuerza re-autenticación deliberadamente para acciones de alto riesgo — esto es el step-up del artículo de factores, aplicado a la sesión: ver datos puede montar sobre la sesión existente, pero cambiar la contraseña, agregar un beneficiario o exportar registros debería exigir un factor fresco aunque la sesión siga válida.


Elegir los números

No hay un valor universal, pero el riesgo de la app ancla el rango. Como punto de partida: las apps de alta sensibilidad (banca, consolas de administración) se inclinan a idle timeouts de decenas bajas de minutos y topes absolutos de unas pocas horas; las apps de productividad ordinarias toleran más en ambos; y cuanto más sensible la acción, más te apoyas en step-up en vez de un timeout global permisivo. El error a evitar es un único timeout generoso para todo — optimiza para la comodidad del flujo de menor riesgo mientras deja el de mayor riesgo expuesto por igual de tiempo. Cualesquiera números elijas, aplícalos del lado servidor: un temporizador del lado cliente que solo oculta la UI deja la sesión subyacente viva y reproducible, lo que no es timeout alguno. Y documenta la justificación, porque “¿por qué son 30 minutos?” es una pregunta que los auditores hacen de forma confiable.


Revocación: terminar una sesión bajo demanda

Los timeouts terminan sesiones eventualmente. La revocación termina una sesión específica ahora — al hacer logout, ante un compromiso detectado, cuando un admin deshabilita una cuenta, cuando se hace offboarding de quien se va. Qué tan difícil es depende por completo de la elección con/sin estado de arriba.


  • Las sesiones del lado servidor revocan limpio: borra o marca el registro, y la siguiente petición falla la validación. Esta es la ventaja operativa decisiva de las sesiones opacas, y por qué el offboarding y la respuesta a incidentes las prefieren.
  • Los JWTs sin estado no tienen registro que borrar, así que necesitas uno de:
    • Vidas cortas + refresh tokens revocables — el access token expira en minutos; revocar el refresh token detiene la renovación. La ventana de exposición queda acotada por la vida del access token en vez de cero.
    • Una denylist de IDs de token revocados (jti) comprobada en cada petición — efectiva, pero reintroduce justo la búsqueda en el servidor que los JWTs querían evitar.
    • Una comprobación de versión de token / “not-before” por usuario — incrementa un contador para invalidar todos los tokens existentes de un usuario a la vez (útil para “cerrar sesión en todas partes” y tras cambio de contraseña).

El resumen honesto: la revocación instantánea y confiable siempre requiere algo de estado del lado servidor. Las sesiones totalmente sin estado cambian revocabilidad por escala — un trade que está bien para APIs de bajo riesgo y es peligroso para cuentas de alto valor. Además rota el identificador de sesión en cada cambio de privilegio — sobre todo justo tras el login — para que un ID de sesión capturado antes de la autenticación no pueda reusarse después (esto vence la session fixation).


Session fixation: por qué rotas el ID en el login

Un ataque merece su propio tratamiento porque la defensa es un hábito, no un flag. En la session fixation, el atacante primero obtiene un ID de sesión válido (muchas apps entregan uno a los visitantes anónimos), y luego engaña a la víctima para que se autentique bajo ese mismo ID — vía un enlace plantado o una cookie fijada. Como la app mantuvo el ID estable a través del login, el atacante, que ya lo conoce, ahora comparte la sesión autenticada de la víctima.


El arreglo es simple e innegociable: rota el identificador de sesión en cada cambio de privilegio, sobre todo justo tras una autenticación exitosa. Emite un ID de sesión nuevo en el login e invalida el previo al login. Un atacante que fijó el ID viejo queda con un valor muerto. La misma rotación aplica en cualquier step-up o elevación de rol — cuando el nivel de confianza de la sesión sube, el identificador debería cambiar para que nada capturado en un nivel inferior pueda montar la mejora.


Por esto la sección de revocación insistió en la rotación de ID junto a timeouts y denylists: cierra un ataque que los flags de cookie seguros por sí solos no cierran.


Sesiones persistentes: “recuérdame” hecho con seguridad

Una cookie de sesión simple muere con el navegador. “Recuérdame” extiende eso deliberadamente — una cookie persistente para que el usuario no sea forzado a re-autenticarse cada día. Cómodo, y un riesgo real si se hace ingenuamente, porque ahora estás guardando una credencial de larga vida en un dispositivo que no controlas.


Buena práctica para el login persistente:


  • Usa un token de recuérdame separado y de larga vida, distinto del token de sesión corto — no simplemente una cookie de sesión con un Max-Age enorme.
  • Que sea un valor aleatorio de alta entropía guardado del lado servidor (hasheado), para que pueda revocarse, y para que una filtración de la base no exponga tokens usables.
  • Rótalo en cada uso y detecta el reuso de un token viejo como señal de robo (alguien reprodujo un token que ya rotaste) — luego invalida toda la cadena.
  • Nunca concedas a una sesión recordada el mismo poder que a una fresca. Un usuario recordado puede navegar; cambiar la contraseña, los datos de pago o los ajustes de seguridad debe seguir disparando re-autenticación step-up. “Recuérdame” restaura comodidad, no confianza total.

Más allá del navegador: apps móviles y sesiones de API

No toda sesión es una cookie. Las apps móviles y los clientes de API suelen cargar un bearer token (a menudo un access token de OAuth, del módulo de protocolos) en un header Authorization: Bearer en vez de una cookie. El concepto es el mismo — una credencial que prueba una sesión autenticada — pero las defensas cambian:


  • SameSite y CSRF en gran medida desaparecen para APIs de puro bearer-token, porque el navegador no adjunta automáticamente una cookie; el cliente envía el token explícitamente. (Los diseños mixtos de cookie-y-token aún necesitan cuidado con CSRF.)
  • El almacenamiento se vuelve el riesgo. Un token en el localStorage del navegador es legible por cualquier XSS — por eso las apps web sensibles a menudo mantienen la sesión en una cookie HttpOnly en vez de almacenamiento accesible por JS. En móvil, los tokens pertenecen al keystore/keychain de la plataforma, no a archivos planos.
  • Access tokens de vida corta más refresh tokens son la norma (haciendo eco de la discusión de JWT): el access token expira en minutos; el refresh token, guardado de forma segura, obtiene uno nuevo y es él mismo revocable.
  • Token binding / DPoP (RFC 9449) endurece los bearer tokens atando criptográficamente un token a la clave del cliente, para que un token robado no pueda reproducirse desde otro dispositivo — atacando directamente la debilidad de “bearer = quien lo tenga”.

El hilo conductor: viva la sesión en una cookie o en un header, es un portador de identidad autenticada, y el trabajo es el mismo — evitar que sea leída, reproducida o que sobreviva a su bienvenida.


Los ataques: CSRF, XSS y session hijacking

La capa de sesión tiene tres ataques característicos. Conocer el control de cada uno es conocimiento central de un profesional.


Session hijacking

Robar un ID de sesión válido y reproducirlo para suplantar al usuario. Rutas de robo: intercepción por texto claro, una cookie legible por JavaScript, filtración en URLs o logs, o levantarlo de una máquina compartida.


Controles: cookies Secure (sin texto claro) + HttpOnly (sin acceso de script); TLS en todos lados; nunca poner IDs de sesión en URLs; rotar el ID tras el login; enlazar sesiones a contexto (dispositivo, red gruesa) y re-verificar ante anomalías; timeouts cortos para encoger la ventana de replay.


Cross-Site Scripting (XSS)

Inyectar script del atacante en una página para que corra en el navegador de la víctima con los privilegios del sitio. Si una cookie de sesión no es HttpOnly, ese script puede leerla y exfiltrarla directamente; incluso con HttpOnly, el script puede montar la sesión para hacer peticiones autenticadas.


Controles: encoding de salida contextual y validación de entrada para detener la inyección en el origen; una Content-Security-Policy (CSP) fuerte para restringir qué scripts corren; HttpOnly para que la cookie siga ilegible. XSS es la razón por la que HttpOnly es innegociable — pero nota que solo oculta la cookie, no arregla la inyección subyacente, que también debes cerrar.


Cross-Site Request Forgery (CSRF)

Engañar al navegador de un usuario con sesión iniciada para que envíe una petición autenticada no deseada a tu sitio (un formulario oculto o etiqueta de imagen disparando un POST que cambia estado). El navegador adjunta la cookie de sesión automáticamente, así que la petición parece legítima.


Controles: cookies SameSite=Lax/Strict (bloquea el envío cross-site clásico); tokens anti-CSRF — un valor impredecible por-sesión/por-petición que el servidor comprueba en peticiones que cambian estado; y comprobar Origin/Referer en endpoints sensibles. Como SameSite solo puede tener casos límite y huecos en navegadores viejos, combínalo con tokens anti-CSRF para cualquier cosa que cambie estado.



Dónde vive el almacén de sesión

Elegir sesiones del lado servidor plantea una pregunta práctica que la gente de JWT gusta de picar: ¿dónde vive el estado, y escala? En una app de un solo servidor, las sesiones en memoria son triviales. En el momento en que corres múltiples instancias tras un balanceador de carga, una sesión en memoria de un servidor es invisible para los demás — así que una petición ruteada a otro lado parece sin sesión.


Tres respuestas comunes:


  • Sticky sessions fijan a un usuario a un servidor. Simple, pero frágil — la falla de ese servidor cierra la sesión de todos los que estaban en él, y complica el escalado.
  • Un almacén de sesión compartido (Redis, Memcached, una base de datos) mantiene las sesiones centralmente para que cualquier instancia pueda leerlas. Este es el enfoque moderno estándar: conserva la revocación instantánea, sobrevive reinicios de instancia, y escala horizontalmente. El costo es una búsqueda de red rápida por petición y un almacén que debes mantener disponible.
  • Estado del lado cliente firmado (el extremo JWT del espectro) elimina el almacén por completo a costa de la revocabilidad, como se cubrió antes.

El punto es que “las sesiones del lado servidor no escalan” es folclore obsoleto — un almacén compartido como Redis maneja volúmenes enormes conservando el control que hace atractivas a las sesiones opacas. El trade real es operativo (correr un almacén) versus seguridad (conservar la revocabilidad), y para la mayoría de apps de alto valor ese trade favorece al almacén.


Logout: qué debería hacer en realidad

El artículo de SSO mostró lo difícil que es el logout entre apps; dentro de una sola app, el logout aún debe hacerse bien o es teatro. Un logout correcto invalida la sesión del lado servidor — borra o marca el registro — para que la credencial esté muerta aunque una copia de la cookie sobreviva. Solo limpiar la cookie en el navegador no basta: si la sesión subyacente sigue válida, una cookie capturada se reproduce de vuelta directo.


Un buen logout también limpia la cookie en el cliente (para que la siguiente visita empiece limpia), e idealmente ofrece “cerrar sesión en todas partes” — invalidando todas las sesiones de un usuario en todos los dispositivos, lo que la técnica de versión de token vuelve barato. Y recuerda el límite del SSO: cerrar sesión de la app no es lo mismo que cerrar sesión del IdP; la UI debería ser honesta sobre cuál acaba de ocurrir. El logout es el único control directo del usuario sobre su propia sesión — debe terminarla de verdad.


La vida de una sesión: un ejemplo trabajado

Ata las piezas con un solo flujo. Sara inicia sesión en una app web de banca en línea.


  1. Login. Se autentica con una passkey. Al tener éxito el servidor emite un ID de sesión fresco (rotando el anónimo — defensa de fixation) y lo fija como cookie HttpOnly; Secure; SameSite=Lax. También registra una sesión del lado servidor con su identidad, roles y marcas de tiempo.
  2. Navegación. Cada petición devuelve la cookie; el servidor la busca y reinicia el reloj idle. Su idle timeout de 15 minutos sigue deslizándose mientras esté activa.
  3. Una acción sensible. Inicia una transferencia. La app no confía en la sesión existente para esto — fuerza step-up, re-verificando su passkey ahora mismo, y podría rotar el ID de sesión de nuevo en esta elevación.
  4. Se aleja. Tras 15 minutos de inactividad el idle timeout termina la sesión del lado servidor; su siguiente clic aterriza en una página de login. Incluso si hubiera seguido activa, un absolute timeout de 8 horas eventualmente forzaría un login fresco.
  5. Robo reportado. Esa noche reporta una laptop perdida. Soporte revoca sus sesiones del lado servidor (borra los registros / incrementa su versión de token); cualquier cookie aún en la laptop ahora falla la validación en la siguiente petición. Como el banco eligió sesiones del lado servidor, esto es instantáneo — un diseño de JWT sin estado tendría que esperar la vida del token o consultar una denylist.

Cada mecanismo de este artículo — flags de cookie, rotación de ID, timeouts idle vs absoluto, step-up, revocación del lado servidor — aparece en una sola sesión ordinaria y defendible.


Una checklist de endurecimiento de sesión

Una lista de revisión compacta que puedes correr contra cualquier aplicación:


  • Flags de cookie: HttpOnly, Secure, SameSite=Lax/Strict, Domain/Path estrechos, sin persistencia innecesaria.
  • ID de sesión: alta entropía, opaco, rotado en el login y en cada cambio de privilegio, nunca puesto en una URL.
  • Timeouts: un timeout idle corto y un tope absoluto más largo, ambos aplicados del lado servidor.
  • Step-up: las acciones sensibles re-autentican incluso dentro de una sesión válida.
  • Revocación: una vía confiable del lado servidor para terminar una sesión ahora (logout, incidente, offboarding); para JWTs, vidas cortas + refresh tokens revocables.
  • Defensas XSS: encoding de salida, validación de entrada y una CSP fuerte — porque HttpOnly limita pero no elimina XSS.
  • Defensas CSRF: SameSite más tokens anti-CSRF en peticiones que cambian estado.
  • Transporte: TLS en todos lados; nunca transmitir ni registrar un ID de sesión en texto claro.
  • Login persistente: tokens de recuérdame separados, rotativos y revocables con privilegio reducido.
  • Clientes no-navegador: tokens en almacenamiento seguro, access corto + refresh, considera DPoP/token binding.

Recapitulación

La sesión es el más allá de la autenticación — y un objetivo primario — así que merece ingeniería deliberada:


  1. Las cookies cargan la sesión; la seguridad está en los atributos — HttpOnly, Secure, SameSite, más Domain/Path estrechos.
  2. Tokens del lado servidor vs JWTs es un trade de revocabilidad y control contra ausencia de estado y escala; un JWT de larga vida como sesión entera es un anti-patrón.
  3. Los timeouts idle y absoluto corren juntos — el idle atrapa el abandono, el absoluto limita la vida y fuerza re-autenticación periódica.
  4. La revocación es instantánea con estado del lado servidor y genuinamente difícil para JWTs sin estado; un “cerrar sesión ahora” real siempre necesita algo de estado, más rotación del ID de sesión para vencer la fixation.
  5. CSRF, XSS y session hijacking tienen cada uno controles específicos y entrelazados — ningún flag por sí solo basta.


Tres preguntas para autoevaluarte

  1. Un colega propone guardar todo el perfil y los roles del usuario en un JWT válido por 24 horas, “para evitar una base de datos de sesión”. Da dos escenarios concretos donde esto te muerde, y cómo lo rediseñarías conservando la mayor parte de la escalabilidad.
  2. Diseña la política de timeout para una app de banca en línea: elige un idle timeout, un absolute timeout y nombra dos acciones que deban forzar re-autenticación step-up incluso a mitad de sesión. Justifica cada número.
  3. Una app fija su cookie de sesión sin HttpOnly y sin SameSite. Nombra el ataque específico que expone cada atributo faltante, y el control adicional que agregarías más allá de solo arreglar los flags.

Ejercicios prácticos

  1. Inspecciona una cookie de sesión real. En un sitio que uses, abre las dev-tools y lee los atributos de la cookie de sesión. Anota cuáles de HttpOnly, Secure y SameSite están puestos. Escribe una frase sobre el riesgo de los que falten.
  2. Decodifica vs busca. Encuentra un JWT (muchas apps exponen uno en local storage o en un header Authorization) y decodifica su payload en un depurador de JWT. Identifica su exp. Pregúntate: si este token fuera robado ahora mismo, ¿cuánto seguiría válido, y podría el servidor detenerlo antes?
  3. Rastrea un logout. Cierra sesión de una app web con la pestaña de red abierta. Determina si la sesión terminó del lado servidor (la cookie vieja ahora falla) o solo se limpió del lado cliente (el valor aún validaría si se reprodujera). ¿Cuál hizo la app?

Preguntas frecuentes

¿Qué hacen los atributos de cookie HttpOnly, Secure y SameSite?

HttpOnly oculta la cookie de JavaScript para que un payload de XSS no pueda leer el ID de sesión. Secure envía la cookie solo por HTTPS, evitando su intercepción en texto claro. SameSite (Strict, Lax o None) controla si la cookie se adjunta a peticiones cross-site, que es la principal defensa a nivel de navegador contra CSRF. Una cookie de sesión debe ser HttpOnly, Secure y SameSite=Lax o Strict.

¿Cuál es la diferencia entre un session token del lado servidor y un JWT para sesiones?

Un session token del lado servidor es un ID aleatorio opaco que apunta a un estado de sesión guardado en el servidor, así que el servidor es la fuente de verdad y puede revocar al instante borrando el registro. Un JWT es un token autocontenido y firmado que el servidor valida sin búsqueda, lo que escala bien pero es difícil de revocar antes de que expire porque no hay nada almacenado que borrar. El trade-off es revocabilidad y control frente a ausencia de estado y escala.

¿Cuál es la diferencia entre un idle timeout y un absolute timeout?

Un idle timeout (sliding) termina la sesión tras un periodo de inactividad y se reinicia en cada petición, así que un usuario activo permanece con sesión iniciada. Un absolute timeout termina la sesión un tiempo fijo después del login sin importar la actividad, limitando la vida total. Los sistemas robustos usan ambos: un idle timeout corto para atrapar sesiones abandonadas y un tope absoluto más largo para forzar re-autenticación periódica.

¿Cómo se revoca una sesión antes de que expire?

Con sesiones del lado servidor borras o marcas el registro de sesión y la siguiente petición falla la validación de inmediato. Con JWTs sin estado no puedes borrar nada, así que o mantienes vidas de token cortas con refresh tokens revocables, o mantienes una denylist / comprobación de versión de token que reintroduce una búsqueda en el servidor. La revocación instantánea real siempre requiere algo de estado del lado servidor.

¿Cuáles son los principales ataques contra las sesiones?

Session hijacking (robar un ID de sesión válido vía intercepción, XSS o una cookie insegura), cross-site scripting (XSS, inyectar script que lee o abusa de la sesión) y cross-site request forgery (CSRF, engañar al navegador para que envíe una petición autenticada). Las defensas centrales son cookies HttpOnly/Secure/SameSite, encoding de salida y CSP contra XSS, tokens anti-CSRF, y rotar el ID de sesión en los cambios de privilegio.