
Autenticación de usuarios con JWT en Node.js y Express paso a paso
La autenticación es una de las partes más importantes de cualquier aplicación web. Si quieres proteger tus rutas, permitir el acceso solo a usuarios registrados y mantener sesiones seguras, una de las formas más comunes es utilizar JSON Web Tokens (JWT).
En este tutorial aprenderás a implementar autenticación con JWT en una aplicación Node.js con Express, paso a paso y de manera sencilla.
¿Qué es JWT?
JWT (JSON Web Token) es un estándar abierto para el intercambio seguro de información entre dos partes. Se utiliza comúnmente para autenticar usuarios en aplicaciones web y móviles.
Un JWT es básicamente una cadena de texto que contiene tres partes:
- Header: información sobre el algoritmo de firma.
- Payload: los datos que queremos guardar (ej. id del usuario).
- Signature: una firma digital que asegura que el token no ha sido manipulado.
Ejemplo de un JWT:
xxxxx.yyyyy.zzzzz
Requisitos previos
- Node.js y npm instalados.
- Conocimientos básicos de Express.
- Una base de datos para guardar usuarios (en este ejemplo usaremos un arreglo en memoria, pero puedes adaptarlo a MySQL o MongoDB).
- Cliente para probar la API (Postman, Insomnia o curl).
Paso 1: Crear el proyecto
Crea la carpeta y el proyecto:
mkdir node-jwt-auth
cd node-jwt-auth
npm init -y
Paso 2: Instalar dependencias necesarias
npm install express jsonwebtoken bcryptjs
- express → framework web.
- jsonwebtoken → genera y valida JWT.
- bcryptjs → encripta contraseñas.
Paso 3: Configurar servidor básico
Archivo index.js
:
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json());
app.get('/', (req, res) => {
res.send('API de autenticación con JWT funcionando 🚀');
});
app.listen(PORT, () => {
console.log(`Servidor corriendo en http://localhost:${PORT}`);
});
Paso 4: Simular base de datos de usuarios
En un archivo users.js
:
const bcrypt = require('bcryptjs');
let usuarios = [];
// Crear usuario con contraseña encriptada
async function crearUsuario(username, password) {
const hashedPassword = await bcrypt.hash(password, 10);
const nuevoUsuario = { id: usuarios.length + 1, username, password: hashedPassword };
usuarios.push(nuevoUsuario);
return nuevoUsuario;
}
// Buscar usuario por nombre
function buscarUsuario(username) {
return usuarios.find(u => u.username === username);
}
module.exports = { usuarios, crearUsuario, buscarUsuario };
Paso 5: Rutas de registro y login
En index.js
agregamos:
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const { usuarios, crearUsuario, buscarUsuario } = require('./users');
const SECRET_KEY = "clave_secreta_super_segura"; // usa dotenv en producción
// Registro
app.post('/register', async (req, res) => {
const { username, password } = req.body;
if (buscarUsuario(username)) {
return res.status(400).json({ mensaje: "Usuario ya existe" });
}
const nuevoUsuario = await crearUsuario(username, password);
res.status(201).json({ mensaje: "Usuario registrado", usuario: { id: nuevoUsuario.id, username: nuevoUsuario.username } });
});
// Login
app.post('/login', async (req, res) => {
const { username, password } = req.body;
const usuario = buscarUsuario(username);
if (!usuario) return res.status(400).json({ mensaje: "Usuario no encontrado" });
const passwordValida = await bcrypt.compare(password, usuario.password);
if (!passwordValida) return res.status(400).json({ mensaje: "Contraseña incorrecta" });
// Crear token
const token = jwt.sign({ id: usuario.id, username: usuario.username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ mensaje: "Login exitoso", token });
});
Paso 6: Middleware para proteger rutas
Agregamos un middleware auth.js
:
const jwt = require('jsonwebtoken');
const SECRET_KEY = "clave_secreta_super_segura";
function verificarToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) return res.status(403).json({ mensaje: "Token requerido" });
jwt.verify(token.split(" ")[1], SECRET_KEY, (err, decoded) => {
if (err) return res.status(401).json({ mensaje: "Token inválido" });
req.user = decoded;
next();
});
}
module.exports = verificarToken;
Y lo usamos en index.js
:
const verificarToken = require('./auth');
// Ruta protegida
app.get('/perfil', verificarToken, (req, res) => {
res.json({ mensaje: "Accediste al perfil", usuario: req.user });
});
Paso 7: Probar la API
Registrar usuario
curl -X POST http://localhost:3000/register -H "Content-Type: application/json" -d '{"username":"david","password":"1234"}'
Login
curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username":"david","password":"1234"}'
Respuesta:
{ "mensaje": "Login exitoso", "token": "xxxxx.yyyyy.zzzzz" }
Acceder a ruta protegida
curl http://localhost:3000/perfil -H "Authorization: Bearer xxxxx.yyyyy.zzzzz"
Paso 8: Buenas prácticas en producción
- Nunca guardes la clave secreta en el código → usa dotenv.
- Configura la expiración del token (
expiresIn
). - Implementa refresh tokens para sesiones largas.
- Usa HTTPS para transmitir los tokens.
- En proyectos grandes, almacena usuarios en una base de datos real (MySQL, MongoDB, PostgreSQL).
Conclusión
Implementar autenticación con JWT en Node.js y Express es más fácil de lo que parece. Con este tutorial, ya tienes un flujo completo de registro, login y rutas protegidas.
Este esquema es la base de muchas aplicaciones modernas: desde APIs REST hasta sistemas de gestión con roles y permisos.
👉 Próximo paso: integrar este sistema de autenticación con una base de datos real y manejar roles de usuario (admin, editor, lector).