Entendiendo el inicio de sesión con cookies y sesiones
El servidor de la API de gestión de muestras que hemos creado hasta ahora tiene un gran problema: cualquiera puede registrar, modificar y eliminar muestras. Al igual que se necesita una tarjeta de acceso para entrar en la sala de equipos en un laboratorio, un servicio web también necesita un "procedimiento para verificar quién es esta persona", es decir, la autenticación.
¿Cómo funciona el inicio de sesión? Para responder a esta pregunta, primero debemos entender las características fundamentales de la web.
HTTP no tiene memoria
El protocolo de comunicación de la web, HTTP, es sin estado (stateless). El servidor olvida inmediatamente quién era el usuario en el momento en que procesa una solicitud y envía una respuesta.
Para ponerlo en perspectiva, es como si el encargado del mostrador de recepción tuviera su memoria restablecida cada 5 segundos. "Por favor, muéstrame los resultados de mi muestra S001" → se entregan los resultados → (restablecimiento) → "Le pregunté antes por la muestra S001" → "¿Quién es usted?".
En cada solicitud, hay que decir "Soy Kim, el investigador". Para solucionar este inconveniente, se inventaron las cookies en 1994.
Cookies: etiquetas que se pegan al navegador
Una cookie es un pequeño dato de texto que el servidor entrega al navegador. El navegador guarda estos datos y los envía automáticamente cada vez que hace una solicitud al mismo servidor.
[1] Solicitud de inicio de sesión
Navegador → servidor: "identificador kim, contraseña 1234"
Servidor → navegador: "¡Verificación completada! Conserva esta cookie"
Set-Cookie: user=kim
[2] Solicitudes posteriores (automáticas)
Navegador → servidor: "Dame la lista de muestras" + Cookie: user=kim
Servidor: "Ah, eres el investigador kim. Te enviaré la lista de muestras"
[3] Otra solicitud (automática)
Navegador → servidor: "Detalles de S001" + Cookie: user=kim
Servidor: "Es una solicitud del investigador kim. Te enviaré la información de S001"Es como una tarjeta de acceso al laboratorio. Una vez que se emite, no es necesario volver a verificar la identidad cada vez; basta con mostrar la tarjeta.
Cómo manejar las cookies en Express
const express = require("express");
const app = express();
app.get("/login", function(req, res) {
res.setHeader("Set-Cookie", "user=kim; Path=/");
res.send("Inicio de sesión completado");
});
app.get("/whoami", function(req, res) {
const cookies = req.headers.cookie;
res.send("Cookies actuales: " + cookies);
});
app.listen(3000);Al acceder a /login, el servidor envía una cookie en la cabecera Set-Cookie, y al acceder a /whoami posteriormente, se puede observar que el navegador envía automáticamente la cookie.
Limitaciones de las cookies: ¿por qué necesitamos sesiones?
Autenticarse solo con cookies presenta problemas importantes. Las cookies se almacenan en el navegador. Al abrir las herramientas de desarrollo del navegador, cualquiera puede ver y modificar el contenido de las cookies.
Si, por ejemplo, se incluye el nombre de usuario directamente en la cookie de esta manera Cookie: user=kim, alguien podría cambiarlo a Cookie: user=admin y hacerse pasar por un administrador.
Para ilustrarlo con una analogía: si en una tarjeta de acceso se indica "Nombre: Kim Yeon-gu", y cualquiera pudiera cambiar el nombre con un trozo de cinta adhesiva, el control de acceso sería inútil.
Las sesiones resuelven este problema.
Sesiones: un registro de acceso gestionado por el servidor
La idea clave de las sesiones es almacenar la información confidencial en el servidor y proporcionar al navegador solo un identificador.
[1] Inicio de sesión correcto
Dentro del servidor: { session_abc123: { user: "kim", role: "researcher" } }
Servidor → navegador: Set-Cookie: session_id=abc123
[2] Solicitud posterior
Navegador → servidor: Cookie: session_id=abc123
Servidor: buscar la sesión abc123 → { user: "kim", role: "researcher" }
→ "Eres el investigador kim"El navegador solo tiene un número sin sentido, abc123. Cambiar este número no sirve de nada si no corresponde a una sesión registrada en el servidor.
Como analogía, es como tener una tarjeta de acceso con solo un código de barras, mientras que la información real de identificación se encuentra en la computadora de la sala de seguridad. Incluso si se copia la tarjeta de acceso, la puerta no se abrirá si el código de barras no está en la base de datos.
| Solo cookies | Sesión (cookies + almacenamiento en el servidor) | |
|---|---|---|
| Ubicación de los datos | Navegador | Servidor |
| Seguridad | El usuario puede modificarlo (riesgoso) | Solo el servidor puede modificarlo (seguro) |
| Capacidad | Límite de 4 KB | Basado en la memoria/base de datos del servidor (sin límite) |
| Analogía | Tarjeta de acceso con el nombre escrito | Tarjeta de acceso con solo un código de barras + base de datos de la sala de seguridad |
Opciones de seguridad de las cookies
También se pueden configurar medidas de seguridad en las propias cookies:
Set-Cookie: session_id=abc123; HttpOnly; Secure; Path=/; Max-Age=3600| Opción | Significado | Motivo |
|---|---|---|
HttpOnly | Impide acceder a la cookie desde JavaScript | Evita que un script malicioso (XSS) robe la cookie |
Secure | Envía la cookie únicamente mediante HTTPS | Evita exponerla por interceptación de la red |
Max-Age=3600 | La elimina automáticamente después de 3600 segundos (1 hora) | Evita mantener indefinidamente un inicio de sesión antiguo |
Path=/ | Solo envía la cookie en solicitudes bajo esta ruta | Limita el ámbito de envío innecesario de la cookie |
Una cookie sin Max-Age desaparece al cerrar el navegador; se denomina cookie de sesión. Una cookie con Max-Age permanece después de cerrar el navegador; se denomina cookie persistente.
Autenticación moderna basada en tokens
Los servicios web modernos utilizan a menudo un JWT (JSON Web Token) en lugar de un identificador de sesión. Supabase, utilizado por BioPlayground, también emplea autenticación basada en JWT.
El principio se parece al de las sesiones, pero existen diferencias:
| Método de sesión | Método con token (JWT) | |
|---|---|---|
| Estado del servidor | Requiere almacenar sesiones | No requiere almacenarlas en el servidor |
| Verificación | Consulta la base de datos de sesiones | Verifica la firma incluida en el token |
| Escalabilidad | Varios servidores deben compartir las sesiones | No requiere compartirlas entre servidores |
En esta etapa no abordaremos una implementación profunda. Lo importante es comprender el mecanismo:
- El usuario envía su identificador y contraseña.
- El servidor los verifica y emite un identificador (ID de sesión o token).
- El navegador adjunta automáticamente el identificador a las solicitudes posteriores.
- El servidor utiliza ese identificador para determinar quién realiza la solicitud.
Todos los sistemas de inicio de sesión son variantes de estas cuatro etapas.
Pruébelo usted mismo (ejemplo con huecos)
Complete los espacios en blanco para terminar el flujo de autenticación basado en cookies.
// 1. Inicio de sesión: el servidor emite una cookieapp.post("/login", function(req, res) {res.setHeader("", "session_id=xyz789; HttpOnly; Path=/");res.json({ message: "Inicio de sesión correcto" });});// 2. API protegida: identifica al usuario mediante la cookieapp.get("/my-samples", function(req, res) {const cookies = req.headers.;if (!cookies || !cookies.includes("session_id")) {return res.status().json({ error: "Es necesario iniciar sesión" });}res.json({ samples: ["S001", "S002"] });});
Errores frecuentes y soluciones
P: La cookie no se envía (req.headers.cookie es undefined)
Compruebe en las herramientas de desarrollo del navegador (F12) → Application → Cookies si existe una cookie para el dominio. Si la opción Secure está activada, no se enviará mediante HTTP (localhost). Durante el desarrollo, retire Secure o utilice HTTPS.
P: Envié la cabecera Set-Cookie, pero el navegador no guarda la cookie
Si el frontend y el backend utilizan dominios o puertos diferentes, la política CORS puede bloquear la cookie. Añada credentials: 'include' a la llamada fetch y configure en el servidor la cabecera Access-Control-Allow-Credentials: true.
P: Explique en una frase la diferencia entre una sesión y una cookie
Una cookie es «un dato almacenado en el navegador»; una sesión es «un sistema que utiliza el identificador de una cookie para localizar datos almacenados en el servidor». La sesión se construye sobre el mecanismo de cookies.