JWT y Node.js: Cómo crear un sistema de autenticación

Entendiendo el concepto de JWT - Tokens Web JSON PORTADA

En este tutorial, aprenderás todo sobre cómo puedes utilizar los JSON Web Tokens (JWT) en Node.js para crear una autenticación de usuarios. Si no estás familiarizado con JWT, puedes seguir el enlace aquí – esto explica todo sobre JWT con muchos ejemplos interesantes.

Te ayudaré a crear APIs para el registro, el inicio de sesión y el cierre de sesión utilizando Node.js. En primer lugar, recordemos los fundamentos de JWT.
El JW-Token consta de 3 partes:

Entendiendo el concepto de JWT - Tokens Web JSON Captura 3

1. Cabecera

La cabecera incluye el tipo de algoritmo utilizado para generar los tokens. Su aspecto es el siguiente:

{
 “alg”: “HS256”,
 “typ”: “JWT”
}

2. Payload

El payload no es más que los datos del usuario.

{
 “id”:”920021",
 “name”: “Krishna”
}

3. Firma

La firma es la clave secreta que genera el servidor.

Y estas 3 partes, cuando se combinan, forman un JW-Token que tiene un aspecto similar al siguiente:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjkyMDAyMSIsIm5hbWUiOiJLcmlzaG5hIn0.tvORZ0xRXmRhVB_sYnckoEN8HYe-q4YUlZJ-ZNaWBiM

Lo primero y más importante es que para completar este tutorial necesitaremos lo siguiente:

  1. Postman: Se utiliza como cliente de API para crear o probar API’s.
  2. npm: El gestor de paquetes de Node (npm) debe estar instalado en tu sistema.
  3. Node.js: Node.js es la plataforma utilizada para construir aplicaciones escalables.

Ahora, vamos a crear un proyecto Node.js.

El primer paso para crear un proyecto Node.js es generar un archivo package.json. Utiliza el siguiente comando:

npm init

Ahora tienes que instalar las dependencias necesarias:

npm install express
npm install jsonwebtoken
npm install nodemon 

Crea un archivo index.js que es el archivo principal del proyecto. Comprueba si la estructura de tu proyecto se parece a la que se muestra a continuación:

Cómo crear un sistema de autenticación usando JWT y Node.js captura 1

Ahora, abre el archivo index.js e importa todos los paquetes o dependencias utilizando el siguiente código:

const express = require('express');
const app = express();
const jwt = require('jsonwebtoken');

Vamos a probar el proyecto. Crea una simple API GET, para comprobar si todo funciona como se espera. Utiliza el siguiente código:

app.get('/api/testing', (req,res) => {
   res.send('¡Hola Desarrollador!')
})
app.listen(9999,() => console.log('El servidor está en funcionamiento'));

Ahora, para probar esta API, tienes que ejecutar el proyecto con el siguiente comando:

nodemon

Abre Postman y añade la siguiente URL:

http://localhost:9999/api/testing

Nota: Comprueba si haces una petición GET desde Postman.

Tu respuesta de éxito debería tener el siguiente aspecto

¡Hola, desarrollador!

Ahora, vamos a crear una API para el registro.

La API de registro obtiene las credenciales de nombre de usuario y contraseña del cliente.

Además, genera un JW-Token para esos datos o payload. Aquí, crearemos un token para ese ID de usuario en particular. Este token se envía de vuelta al lado del cliente.

API de registro

app.post('/api/signup' , (req,res) => {
   const id  = req.body.id;
   const username = req.body.username;
   const password = req.body.password;
   jwt.sign(id , 'secret_key' , (err,token) => {
      if(err){
         res.status(400).send({msg : 'Error'})
      }
 else {
         res.send({msg:'success' , token: token})
      }
   })
})

Nota: Aquí no vamos a guardar los datos en la base de datos porque queremos centrarnos más en la comprensión del concepto JWT.

Una vez que ejecutes este código, la respuesta de Postman será la siguiente:

Respuesta del JWT

{
"msg": "success",
"token":"eyJhbGciOiJIUzI1NiJ9.MQ.gaKRuIIRNvXiTlyNPE1Kp3SpAQfhrI3r9MrSB1YdMz8"
}

La respuesta devuelve un mensaje de éxito con un JW-Token que está encriptado y que también lleva Encabezado, Datos(id) y Firma. Ahora, este token va a ayudar a los usuarios a realizar todas las solicitudes de rutas protegidas.

Ahora, sigamos con la API de inicio de sesión.

Entendiendo el concepto de JWT - Tokens Web JSON Captura 4

Antes de crear la API de inicio de sesión, tenemos que crear una función de middleware para verificar el token que se envía desde el lado del cliente al lado del servidor.

Nota: Las funciones del middleware son funciones que tienen acceso al objeto solicitud, al objeto respuesta y a la siguiente función del ciclo solicitud-respuesta de la aplicación.

function verifyToken(req, res, next) {
   const authHeader = req.headers["authorization"];
   const token = authHeader && authHeader.split(" ")[1];
   if (token == null) return res.sendStatus(403);
   jwt.verify(token, "secret_key", (err, user) => {
      if (err) return res.sendStatus(404);
      req.user = user;
      next();
   });
}

Esta función de middleware nos ayudará a verificar el token que se pasa del lado del cliente al lado del servidor en cada solicitud de ruta protegida. Y podemos utilizar este middleware en nuestra API simplemente añadiéndolo como parámetro entre los puntos finales de la API y la función de devolución de llamada.

API de inicio de sesión

app.post('/api/login' , verifyToken , (req,res) => {
   res.send('You are Authorized!')
})

Este es el truco para enviar la respuesta. Si solicitas esta API desde Postman, seguramente dará un error – 403 No autorizado. Esa es la razón por la que utilizamos un middleware dentro de la API. Ahora, para trabajar con esta ruta protegida, tienes que establecer las Cabeceras dentro de Postman.

Nota: Para establecer las cabeceras, ve a la opción de cabeceras, añade una clave ‘authorization’ con el valor ‘bearer <token> ‘. Comprueba la siguiente imagen.

Cómo crear un sistema de autenticación usando JWT y Node.js captura 2

Haz clic en la casilla de la izquierda para comprobar y enviar una solicitud de acceso. Debería responder con «Estás autorizado».

API de cierre de sesión

Ahora tenemos que crear la API de cierre de sesión.

Para crear la API de cierre de sesión, primero tenemos que comprobar si la solicitud es válida y luego dar la respuesta a esa solicitud. Y aquí, el paso importante es que para cerrar la sesión de un usuario, entre bastidores, tenemos que eliminar el token JWT de las cabeceras. Pero, por desgracia, no tenemos ninguna opción para eliminar el token JWT de las Cabeceras. Por lo tanto, sustituiremos el token JWT por una cadena en blanco que expirará en 1 segundo. El código para esto es el siguiente:

app.put("/api/logout", authToken, function (req, res) {
   const authHeader = req.headers["authorization"];
   jwt.sign(authHeader, "", { expiresIn: 1 } , (logout, err) => {
      if (logout) {
         res.send({msg : 'Has sido desconectado' });
      } else {
         res.send({msg:'Error'});
      }
   });
});

Esta API sólo funcionará cuando envíes una solicitud añadiendo un JW-Token con cabeceras, que responda de la siguiente manera:

{
"msg": "Has sido desconectado"
}

Y así es cómo hemos construido con éxito un sistema de autorización y espero que todos hayáis captado la idea básica de cómo funciona el JWT. Y ya sabes, si te queda algún tipo de duda, comentario aquí abajo y te responderé lo antes posible.