Autorización y autenticación en JavaScript (Node.js)
En el desarrollo web moderno con Node.js, la seguridad de los datos del usuario y el control de acceso son tareas críticas. La autenticación (verificación de identidad) y la autorización (verificación de permisos) son los dos pilares de cualquier sistema protegido. En este artículo, analizaremos las herramientas y bibliotecas clave para implementar estos mecanismos en la plataforma Node.js.
Conceptos básicos
Autenticación — el proceso de verificar que un usuario es quien dice ser (generalmente mediante usuario/contraseña, tokens o biometría). Autorización — la determinación de qué acciones y recursos están disponibles para un usuario autenticado (roles, permisos de acceso).
Bibliotecas populares para Node.js
1. Passport.js — estrategia de autenticación universal
Passport.js es la biblioteca middleware más popular para Express. Soporta más de 500 estrategias: local (usuario/contraseña), OAuth2 (Google, Facebook, GitHub), JWT y muchas otras.
const passport = require('passport');const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy( function(username, password, done) { User.findOne({ username: username }, function (err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Nombre de usuario incorrecto' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Contraseña incorrecta' }); } return done(null, user); }); }));
// Serialización y deserialización del usuariopassport.serializeUser(function(user, done) { done(null, user.id);});
passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); });});2. JSON Web Tokens (JWT) — autenticación sin sesión
La biblioteca jsonwebtoken permite crear y verificar tokens JWT. Es ideal para API REST y aplicaciones SPA.
const jwt = require('jsonwebtoken');const secretKey = process.env.JWT_SECRET;
// Creación del token al iniciar sesiónconst token = jwt.sign( { userId: user.id, role: user.role }, secretKey, { expiresIn: '24h' });
// Middleware para verificar el tokenfunction authMiddleware(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
if (!token) return res.status(401).json({ error: 'Token no proporcionado' });
jwt.verify(token, secretKey, (err, decoded) => { if (err) return res.status(403).json({ error: 'Token no válido' }); req.user = decoded; next(); });}3. bcrypt — hash seguro de contraseñas
¡Nunca almacene contraseñas en texto plano! bcrypt es el estándar de oro para el hash con sal.
const bcrypt = require('bcrypt');const saltRounds = 10;
// Hash de la contraseña al registrarseasync function hashPassword(plainPassword) { const salt = await bcrypt.genSalt(saltRounds); const hash = await bcrypt.hash(plainPassword, salt); return hash;}
// Verificación de la contraseña al iniciar sesiónasync function checkPassword(plainPassword, hash) { return await bcrypt.compare(plainPassword, hash);}4. express-session + connect-redis — gestión de sesiones
Para aplicaciones web tradicionales con sesiones del lado del servidor, use express-session junto con Redis para escalar.
const session = require('express-session');const RedisStore = require('connect-redis')(session);
app.use(session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', // HTTPS httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 1 día }}))