Volver a la lista

Passport.js: middleware de autenticación.

Comprenda la estructura de Passport.js y la estrategia Local, e implemente la autenticación de inicio de sesión en Express.

Intermedio
|
12min
|
Verificado (2026-07)
Passport.jsmiddleware de autenticaciónEstrategia LocalSerializaciónAutenticación por sesión
Progreso0/55 (0%)

Passport.js: Middleware de autenticación

Al finalizar este tema

Comprenderá la utilidad de Passport.js, podrá implementar la autenticación con ID y contraseña mediante la estrategia Local y explicará la función de serialización y deserialización.


¿Por qué usar Passport.js?

En el tema anterior, implementamos manualmente la autenticación basada en sesiones. Aunque funciona, el código se vuelve más complejo a medida que aumenta el número de métodos de autenticación.

  • Inicio de sesión con ID y contraseña
  • Inicio de sesión con Google
  • Inicio de sesión con GitHub
  • Autenticación con token JWT

Implementar cada uno manualmente dispersaría la lógica de autenticación entre las diferentes rutas. Passport.js es un middleware especializado en autenticación que resuelve este problema. Ofrece más de 500 estrategias de autenticación en forma de complementos.


Concepto clave: Patrón Strategy

Passport.js utiliza el patrón Strategy. Separa la pregunta "¿cómo autenticar?" en objetos Strategy.

text
Passport.js (framework)
├── Estrategia Local    → ID/contraseña
├── Google Strategy   → Google OAuth
├── GitHub Strategy   → GitHub OAuth
└── JWT Strategy      → JSON Web Token

Cada estrategia es un paquete npm independiente. Instala solo lo que necesites.


Instalación

bash
npm install passport passport-local express-session
  • passport: Biblioteca principal
  • passport-local: Estrategia de autenticación por ID y contraseña
  • express-session: Gestión de sesiones (Passport se utiliza internamente)

Configuración de la estrategia local

javascript
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const app = express();

// Base de datos de usuarios ficticia
const users = [
  { id: 1, username: 'alice', password: 'pass123', displayName: 'Alice Kim' },
  { id: 2, username: 'bob', password: 'pass456', displayName: 'Bob Lee' }
];

// 1. Registro de estrategia
passport.use(new LocalStrategy(
  (username, password, done) => {
    const user = users.find(u => u.username === username);
    if (!user) {
      return done(null, false, { message: 'User not found' });
    }
    if (user.password !== password) {
      return done(null, false, { message: 'Wrong password' });
    }
    return done(null, user);
  }
));

done Tres patrones de llamada a funciones de devolución:

LlamadaSignificado
done(null, user)Autenticación exitosa. Se pasa el objeto de usuario
done(null, false, {message})Autenticación fallida. Usuario no encontrado o contraseña incorrecta
done(err)Error del sistema. Fallo en la conexión a la base de datos, etc.

Serializar / Deserializar

Almacenar el objeto completo del usuario en la sesión consume memoria innecesariamente. Passport almacena en la sesión solo la información de identificación mínima (generalmente el ID) y restaura al usuario a partir de ese ID en cada solicitud.

javascript
// Datos a guardar en la sesión (una vez al iniciar sesión)
passport.serializeUser((user, done) => {
  done(null, user.id);  // Guardar solo user.id en la sesión
});

// 3. Restaurar usuario desde la sesión (en cada solicitud)
passport.deserializeUser((id, done) => {
  const user = users.find(u => u.id === id);
  done(null, user);     // Configurar objeto de usuario completo en req.user
});
text
Al iniciar sesión:   objeto user → serializeUser → guardar id=1 en la sesión
En cada solicitud:  id=1 desde la sesión → deserializeUser → restaurar objeto user → req.user

Al consultar la base de datos en deserializeUser, se guarda solo el ID en la sesión, lo que permite acceder a la información del usuario más reciente en cada solicitud.


Conexión del middleware

javascript
// 4. Configuración del middleware (¡el orden es importante!)
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(session({
  secret: process.env.SESSION_SECRET || 'dev-secret',
  resave: false,
  saveUninitialized: false
}));
app.use(passport.initialize());   // Inicialización de Passport
app.use(passport.session());      // Conexión con la sesión

El orden es importante: express-sessionpassport.initialize()passport.session(). Si se altera el orden, la sesión no funcionará correctamente.


Rutas de inicio y cierre de sesión

javascript
// Inicio de sesión
app.post('/login',
  passport.authenticate('local', {
    successRedirect: '/dashboard',
    failureRedirect: '/login',
    failureMessage: true
  })
);

// O cuando se desea una respuesta JSON
app.post('/api/login', (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) return next(err);
    if (!user) {
      return res.status(401).json({ error: info.message });
    }
    req.logIn(user, (err) => {
      if (err) return next(err);
      res.json({ message: `Welcome, ${user.displayName}` });
    });
  })(req, res, next);
});

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

passport.authenticate('local') ejecuta la estrategia LocalStrategy que se registró previamente. Si la ejecución es exitosa, se llama a serializeUser y el ID de usuario se guarda en la sesión.


Rutas protegidas

javascript
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.status(401).json({ error: 'Login required' });
}

app.get('/dashboard', ensureAuthenticated, (req, res) => {
  res.json({
    message: `Hello, ${req.user.displayName}`,
    user: { id: req.user.id, username: req.user.username }
  });
});

req.isAuthenticated() es un método que proporciona Passport y que devuelve true si hay un usuario válido en la sesión. req.user es el objeto de usuario recuperado de deserializeUser.


Resumen del flujo completo

text
1. Iniciar servidor
   passport.serializeUser()       — Registrar método de almacenamiento de sesión
   passport.deserializeUser()     — Registrar método de restauración de sesión
   passport.deserializeUser()     — Registrar método de restauración de sesión

2. POST /login
   passport.authenticate('local') — Ejecutar estrategia
   → Éxito: serializeUser → Guardar ID en la sesión → Respuesta
   → Fallo: respuesta 401

3. GET /dashboard (autenticación requerida)
   Verificar cookie de sesión → deserializeUser → configurar req.user
   ensureAuthenticated → req.isAuthenticated() → true → ejecución de ruta

4. POST /logout
   req.logout() → eliminación del usuario en la sesión → respuesta

Errores comunes

ErrorConsecuenciaSolución
Llamar a passport.session() antes de app.use(session(...))La sesión no se inicializaOrden: express-sessionpassport.initialize()passport.session()
Guardar el objeto user completo en serializeUserEl tamaño de la sesión aumenta excesivamenteGuardar solo user.id
Ignorar errores asíncronos en deserializeUserEl servidor falla cuando la autenticación no se realiza correctamenteLlamar a done(err)
Omitir la llamada a done() en la función de retorno de StrategyLa solicitud se queda en espera indefinidaVerificar que se llame a done() en todas las ramas

Resumen

ConceptoDescripción
Passport.jsMiddleware especializado en autenticación. Admite varios métodos de autenticación mediante el patrón Strategy
StrategyObjeto que encapsula un método de autenticación (Local, Google, JWT, etc.)
serializeUserDetermina la información mínima que se debe guardar en la sesión (normalmente user.id)
deserializeUserRestaura el objeto de usuario a partir del ID de la sesión en cada solicitud
req.userUsuario actualmente autenticado restaurado por deserializeUser
req.isAuthenticated()Verifica si el usuario ha iniciado sesión

El valor de Passport.js reside en la "estandarización de la lógica de autenticación". Al cambiar de Local a Google OAuth, solo se debe reemplazar la Strategy. serialize/deserialize, la cadena de middleware y req.user permanecen sin cambios en el resto del código.

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