Volver a la lista

Sesiones y autenticación: Express Session

Aprenderás cómo funciona la autenticación basada en sesiones en Express, su relación con las cookies y el concepto de almacén de sesiones (session store).

Intermedio
|
12min
|
Verificado (2026-07)
sesiónexpress-sessionautenticacióninicio de sesiónalmacén de sesiones
Progreso0/55 (0%)

Sesiones y autenticación — Express Session

Al finalizar este tema

Comprenderá por qué son necesarias las sesiones, podrá implementar el inicio y cierre de sesión con express-session y conocerá el concepto de almacén de sesiones (session store) y su configuración de seguridad.


¿Por qué son necesarias las sesiones?

En el tema de cookies aprendió que "HTTP es sin estado". Aunque las cookies permiten mantener el estado, tienen limitaciones críticas.

javascript
// Mal — Almacenar información del usuario directamente en la cookie
res.cookie('user', JSON.stringify({ id: 1, role: 'admin' }));

El cliente (navegador) puede modificar las cookies libremente. ¿Qué ocurre si el usuario cambia role: 'admin' por role: 'superadmin' y lo envía? El servidor no puede distinguirlo.

Las sesiones resuelven este problema. Los datos sensibles se almacenan en el servidor y al cliente solo se le entrega una clave de identificación (ID de sesión).

text
Método de cookies:  Almacena "nombre=Hoon, rol=admin" en el cliente (sujeto a falsificación)
Método de sesión:  Almacena solo "sessionID=abc123" en el cliente → El servidor consulta la información del usuario con abc123

Funcionamiento de la sesión

text
1. Solicitud de inicio de sesión
   Client → Server: POST /login {username: "Hoon", password: "****"}

2. El servidor crea la sesión
   Server: Almacena {userId: 1, rol: "admin"} en el almacén de sesiones
   Server: Genera ID de sesión = "abc123"
   Server → Client: Set-Cookie: connect.sid=abc123

3. Solicitudes posteriores
   Client → Server: GET /dashboard (Cookie: connect.sid=abc123)
   Server: Consulta la sesión con abc123 → Verifica {userId: 1, rol: "admin"}
   Server → Client: Datos del panel

El cliente solo conoce el ID de sesión, mientras que los datos reales (userId, role) se encuentran en la memoria del servidor o en la base de datos. Si el cliente falsifica el ID de sesión, la autenticación fallará si dicho ID no existe en el almacén de sesiones del servidor.


Instalación y configuración de express-session

bash
npm install express-session
javascript
const express = require('express');
const session = require('express-session');
const app = express();

app.use(express.json());
app.use(session({
  secret: 'my-secret-key-change-this',
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: false,      // En producción, usar true
    maxAge: 3600000      // 1 hour
  }
}));
OpciónDescripción
secretClave para cifrar el ID de sesión. Debe ser larga y aleatoria.
resaveIndica si se debe guardar la sesión en cada solicitud, incluso sin cambios. Se recomienda false.
saveUninitializedIndica si se deben guardar también las sesiones vacías. Si se usa false, la cookie no se emitirá antes del inicio de sesión.
cookieOpciones de la cookie de sesión (httpOnly, secure, maxAge, etc.)

secret nunca debe escribirse directamente en el código (hardcoding). Debe gestionarse mediante variables de entorno:

javascript
secret: process.env.SESSION_SECRET || 'fallback-dev-only'

Implementación de inicio y cierre de sesión

javascript
const users = [
  { id: 1, username: 'alice', password: 'pass123', role: 'admin' },
  { id: 2, username: 'bob', password: 'pass456', role: 'user' }
];

// Inicio de sesión
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username && u.password === password);

  if (!user) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // Guardar información del usuario en la sesión
  req.session.userId = user.id;
  req.session.role = user.role;

  res.json({ message: `Welcome, ${user.username}` });
});

// Cierre de sesión
app.post('/logout', (req, res) => {
  req.session.destroy(err => {
    if (err) {
      return res.status(500).json({ error: 'Logout failed' });
    }
    res.clearCookie('connect.sid');
    res.json({ message: 'Logged out' });
  });
});

req.session es un objeto. Puedes almacenar cualquier propiedad libremente. req.session.destroy() elimina los datos de sesión del servidor.


Middleware de autenticación

Cada vez que se accede a una ruta protegida, es necesario verificar si el usuario ha iniciado sesión. Al implementar esto como un middleware, se puede reutilizar en todas las rutas.

javascript
function requireAuth(req, res, next) {
  if (!req.session.userId) {
    return res.status(401).json({ error: 'Login required' });
  }
  next();
}

function requireAdmin(req, res, next) {
  if (req.session.role !== 'admin') {
    return res.status(403).json({ error: 'Admin access required' });
  }
  next();
}

// Uso
app.get('/profile', requireAuth, (req, res) => {
  res.json({ userId: req.session.userId, role: req.session.role });
});

app.get('/admin/dashboard', requireAuth, requireAdmin, (req, res) => {
  res.json({ message: 'Admin dashboard' });
});

Es posible crear condiciones compuestas, como "inicio de sesión + administrador", mediante el encadenamiento de middlewares.


Almacén de sesiones: memoria frente a almacenamiento externo

De forma predeterminada, express-session almacena las sesiones en la memoria del servidor. Esto es suficiente para el desarrollo, pero presenta problemas en producción.

ProblemaDescripción
Reinicio del servidorLa memoria se inicializa, por lo que todos los usuarios cierran sesión.
Fuga de memoriaSi las sesiones se acumulan, la memoria del servidor puede agotarse.
Múltiples servidoresEl servidor B no reconoce las sesiones almacenadas en la memoria del servidor A.

En producción, se utilizan almacenes externos como Redis, MongoDB o PostgreSQL:

bash
npm install connect-redis redis
javascript
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');

const redisClient = createClient();
redisClient.connect();

app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false
}));

Almacenar las sesiones en Redis permite que estas persistan incluso tras reiniciar el servidor, y permite compartir sesiones entre varios servidores si todos apuntan al mismo Redis.


Sesiones vs. JWT: ¿cuándo usar cada una?

SesiónJWT
EstadoServidor (stateful)Cliente (stateless)
EscalabilidadRequiere un almacenamiento compartido como RedisNo requiere compartir entre servidores
Cierre de sesióndestroy() Invalidación inmediataVálido hasta la expiración del token (requiere lista negra)
SeguridadEl servidor gestiona los datosDifícil de mitigar en caso de robo del token
Casos de uso adecuadosAplicaciones web tradicionales, paneles de administraciónServidores API, aplicaciones móviles, microservicios
text
Aplicaciones web tradicionales (SSR) → Las sesiones son naturales
SPA + Servidor API → JWT es conveniente
Aplicaciones móviles → JWT (la gestión de cookies es compleja

Resumen clave

ConceptoResumen
SesiónAlmacena los datos del usuario en el servidor y solo envía el ID al cliente
ID de sesiónClave de identificación transmitida mediante cookies (connect.sid)
req.sessionObjeto para leer y escribir datos de la sesión
destroy()Cierre de sesión: elimina los datos de la sesión
Almacén de sesionesEn entornos de producción, se utilizan almacenes externos como Redis

El principio fundamental de la autenticación basada en sesiones: los datos sensibles se quedan en el servidor y al cliente solo se le entrega la llave (ID de sesión). Al comprender este principio, se pueden entender naturalmente las diferencias con la autenticación basada en tokens (JWT).

💬 Preguntas y comentarios

0 comentarios

Puedes publicar sin iniciar sesión. Los comentarios de invitados no pueden editarse ni eliminarse después.

0/2000

Cargando...