Introducción
La autenticación JWT (JSON Web Token) es una técnica popular para autenticar y autorizar usuarios en aplicaciones web. JWT es un estándar abierto (RFC 7519) que define una forma compacta y autónoma de transmitir información de manera segura entre las partes como un objeto JSON. Esta información puede ser verificada y confiada porque está firmada digitalmente.
¿Por qué usar JWT?
- Compacto: Los tokens JWT son compactos y pueden ser enviados a través de URL, parámetros POST o en un encabezado HTTP.
- Autónomo: El token contiene toda la información necesaria sobre el usuario, eliminando la necesidad de almacenar sesiones en el servidor.
- Seguro: Los tokens pueden ser firmados usando un secreto (con el algoritmo HMAC) o un par de claves pública/privada (con RSA o ECDSA).
Estructura de un JWT
Un JWT consta de tres partes separadas por puntos (.
):
- Header (Encabezado): Contiene el tipo de token (JWT) y el algoritmo de firma.
- Payload (Carga útil): Contiene las declaraciones (claims). Estas pueden ser declaraciones registradas, públicas y privadas.
- Signature (Firma): Se utiliza para verificar que el mensaje no ha sido alterado.
Ejemplo de un JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- Header:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
- Payload:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
- Signature:
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Implementación de JWT en Node.js
Instalación de Dependencias
Para implementar JWT en una aplicación Node.js, utilizaremos el paquete jsonwebtoken
. También necesitaremos express
para crear nuestro servidor y body-parser
para manejar las solicitudes POST.
Configuración del Servidor
Primero, configuraremos un servidor básico con Express.
const express = require('express'); const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const app = express(); const PORT = 3000; app.use(bodyParser.json()); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
Creación de un Endpoint para Autenticación
Vamos a crear un endpoint /login
que generará un token JWT cuando un usuario se autentique correctamente.
const users = [ { id: 1, username: 'user1', password: 'password1' }, { id: 2, username: 'user2', password: 'password2' } ]; app.post('/login', (req, res) => { const { username, password } = req.body; const user = users.find(u => u.username === username && u.password === password); if (user) { const token = jwt.sign({ id: user.id, username: user.username }, 'your_jwt_secret', { expiresIn: '1h' }); res.json({ token }); } else { res.status(401).json({ message: 'Invalid credentials' }); } });
Middleware de Autenticación
Para proteger rutas específicas, crearemos un middleware que verificará el token JWT.
const authenticateJWT = (req, res, next) => { const token = req.header('Authorization'); if (token) { jwt.verify(token, 'your_jwt_secret', (err, user) => { if (err) { return res.sendStatus(403); } req.user = user; next(); }); } else { res.sendStatus(401); } };
Rutas Protegidas
Ahora podemos proteger nuestras rutas utilizando el middleware authenticateJWT
.
app.get('/protected', authenticateJWT, (req, res) => { res.json({ message: 'This is a protected route', user: req.user }); });
Ejercicio Práctico
Ejercicio
- Objetivo: Implementar un sistema de autenticación JWT en una aplicación Node.js.
- Tareas:
- Crear un servidor Express.
- Implementar un endpoint
/login
que genere un token JWT. - Crear un middleware de autenticación JWT.
- Proteger una ruta
/protected
utilizando el middleware de autenticación.
Solución
const express = require('express'); const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const app = express(); const PORT = 3000; app.use(bodyParser.json()); const users = [ { id: 1, username: 'user1', password: 'password1' }, { id: 2, username: 'user2', password: 'password2' } ]; app.post('/login', (req, res) => { const { username, password } = req.body; const user = users.find(u => u.username === username && u.password === password); if (user) { const token = jwt.sign({ id: user.id, username: user.username }, 'your_jwt_secret', { expiresIn: '1h' }); res.json({ token }); } else { res.status(401).json({ message: 'Invalid credentials' }); } }); const authenticateJWT = (req, res, next) => { const token = req.header('Authorization'); if (token) { jwt.verify(token, 'your_jwt_secret', (err, user) => { if (err) { return res.sendStatus(403); } req.user = user; next(); }); } else { res.sendStatus(401); } }; app.get('/protected', authenticateJWT, (req, res) => { res.json({ message: 'This is a protected route', user: req.user }); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
Conclusión
En esta sección, hemos aprendido cómo implementar la autenticación JWT en una aplicación Node.js. Hemos cubierto la estructura de un JWT, cómo generar un token, cómo crear un middleware de autenticación y cómo proteger rutas específicas. La autenticación JWT es una técnica poderosa y eficiente para manejar la autenticación y autorización en aplicaciones modernas.
Curso de Node.js
Módulo 1: Introducción a Node.js
Módulo 2: Conceptos Básicos
Módulo 3: Sistema de Archivos y E/S
Módulo 4: HTTP y Servidores Web
- Creando un Servidor HTTP Simple
- Manejo de Solicitudes y Respuestas
- Sirviendo Archivos Estáticos
- Enrutamiento
Módulo 5: NPM y Gestión de Paquetes
- Introducción a NPM
- Instalación y Uso de Paquetes
- Creación y Publicación de Paquetes
- Versionado Semántico
Módulo 6: Framework Express.js
- Introducción a Express.js
- Configuración de una Aplicación Express
- Middleware
- Enrutamiento en Express
- Manejo de Errores
Módulo 7: Bases de Datos y ORMs
- Introducción a las Bases de Datos
- Usando MongoDB con Mongoose
- Usando Bases de Datos SQL con Sequelize
- Operaciones CRUD
Módulo 8: Autenticación y Autorización
- Introducción a la Autenticación
- Usando Passport.js
- Autenticación JWT
- Control de Acceso Basado en Roles
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias con Mocha y Chai
- Pruebas de Integración
- Depuración de Aplicaciones Node.js
Módulo 10: Temas Avanzados
- Módulo Cluster
- Hilos de Trabajo
- Optimización del Rendimiento
- Construcción de APIs RESTful
- GraphQL con Node.js
Módulo 11: Despliegue y DevOps
- Variables de Entorno
- Usando PM2 para la Gestión de Procesos
- Desplegando en Heroku
- Integración y Despliegue Continuos