Tutorial

Guía completa de autenticación JWT en Node.js y Express para principiantes

David Zambrano
9/24/2025
30 minutos
21 vistas
Node.js

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:

  1. Header: información sobre el algoritmo de firma.
  2. Payload: los datos que queremos guardar (ej. id del usuario).
  3. 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

  1. Registrar usuario

    curl -X POST http://localhost:3000/register    -H "Content-Type: application/json"    -d '{"username":"david","password":"1234"}'
    
  2. 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"
    }
    
  3. 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).