Implementar JSON Web Tokens con NodeJS

implementando JSON Web Tokens con NodeJS - Cuarta parteJSON Web Tokens o simplemente JTW, es una herramienta que nos permite autenticarnos con el servidor mediante Tokens de una forma simple y segura. Los Tokens son una cadena de alfanum茅rica, que es generada por el servidor y es enviada al cliente para autenticaciones futuras, evitando tener que enviar credenciales en cada invocaci贸n.

Te recomiendo que te des una venta a mi art铆culo Autenticaci贸n con JSON Web Tokens, el cual abordo toda la teor铆a, por si no est谩s familiarizado con el concepto de Tokens y la forma de trabajar.

Este art铆culo es parte de una colecci贸n de art铆culo en donde explico c贸mo Construir un API REST con NodeJS, por lo que si estas interesado puede regresar desde el comienzo.

Implementando JWT en un API REST

Lo primero ser谩 instalar el m贸dulo de JWT, para lo cual, ejecutaremos el comando npm install --save jsonwebtoken body-parser聽, una vez hecho esto, tendremos que implementar un servicio de autenticaci贸n tradicional, el cual reciba usuario y contrase帽a y nos regrese un token en caso de 茅xito. El servicio quedar铆a de la siguiente manera:

La funci贸n login recibe como par谩metro el usuario ( req.body.user聽) y el password ( req.body.password聽), los cuales los tendremos que validar contra nuestros usuarios, sin embargo, en este caso, para hacerlo m谩s simple, lo hemos validado contra el usuario oscar/1234, si la autenticaci贸n falla, entonces regresamos un error al cliente. Por otra parte, si todo sale bien, creamos un token al usuario, el cual tiene una vigencia de 24 horas, para finalmente retornarlo.

Veamos un ejemplo de autenticaci贸n:

Creando el Token JWS

En la imagen pasada hemos enviado las credenciales correctas para que nos genere un token, sin embargo, no se puede ver correctamente debido a su longitud, es por ello que lo ponemos por a continuaci贸n:

Este token deber谩 ser guardado por el usuario para futuras invocaciones al API.

Autentic谩ndonos mediante Tokens

El siguiente paso ser谩 crear un servicio protegido que valida la existencia del token, de lo contrario, evitar谩 el acceso, para ello crearemos un servicio de prueba llamado secure:

Como podemos observar, lo primero que tenemos que hacer, es recuperar el header correspondiente al token, es decir, el token 鈥 authorization聽鈥, si este header no se encuentra, entonces retornamos un c贸digo 401 (No autorizado) y regresamos el motivo del error.

El siguiente paso es algo confuso, pues al token hay que retirarla el substring 鈥 Baerer聽鈥, este String es parte de las especificaciones de HTTP, y es agredo de forma autom谩tica, por lo que no entraremos en detalles, simplemente lo retiramos.

Finalmente, validamos el token mediante el m茅todo verify, el cual validar谩 que el token sea v谩lido y adem谩s que no est茅 caducado, en cualquiera de estos dos casos, un error 401 es retornado junto con el mensaje de error. Finalmente, si todo sale bien, procedemos con la operaci贸n de negocio.

El siguiente request es enviado son el header, retornando un error 401 y su mensaje de error correspondiente:

Validacion fallida del token JWT

Este nuevo request es enviado con el header 鈥 authorization聽鈥 el cual corresponde a un token v谩lido generado por el servicio de login:

NOTA: Siempre ser谩 mejor usar un middleware para validar el token, de esta forma, evitamos tener que validar el token en cada invocaci贸n, sin embargo, lo hemos hecho as铆 para hacer m谩s f谩cil el ejemplo.

8 thoughts to “Implementar JSON Web Tokens con NodeJS”

  1. Observaci贸n en el primer c贸digo le hace falta esto:

    Instalar body parser:
    npm install -save body-parser
    e invocarlo:
    var bodyParser = require(‘body-parser’);

    Duda, si yo quiero tener un JS separado del server.js para introducir el c贸digo del JWT para luego nada mas invocarlo en mis servicios rest, 驴como ser铆a?

    1. Gracias por las observaciones, las tomar茅 en cuenta.

      Con respecto a tu pregunta, eso es muy simple, solo creas las funciones que creas necesarias en un archivos JS separado, y al final del archivo las exportas (module.exports) y luego solo importas el archivos JS desde server.js y utilizas la funci贸n.

      saludos.

  2. Gracias por esta implementaci贸n, muy clara e 煤til.
    Pero no entend铆 la nota final ” Siempre ser谩 mejor usar un middleware para validar el token, de esta forma, evitamos tener que validar el token en cada autenticaci贸n”.

    1. Hola Juan, primero que nada, te comento que el p谩rrafo estaba mal parafraseado, la redacci贸n correcta ser铆a “evitamos tener que validar el token en cada invocaci贸n“, dicho esto, lo que quiero decir es que mediante un middleware, podemos interceptar todas las invocaciones y validar el token en un solo punto, en otro caso, tendr铆amos que implementar la l贸gica de validaci贸n en cada uno de los servicios.

  3. Un ejemplo de middleware para evitar la validaci贸n al consumir cada servicio. Como seria? Puede explicar en por qu茅 usar middleware

    1. Hola Jos茅, lo que puedes hacer es implementar tu propio Middleware donde tu mismo puedes poner la l贸gica para validar si un servicio debe o no tener seguridad, en mi libro de “Aplicaciones reactivas con React, NodeJS y MongoDB” explico esto, puedes ver como implemente esta l贸gica en el siguiente archivos JS, donde indico que todas las rutas que comiencen con /secure deber谩n tener token forzosamente, y el resto podr谩n continuar son tokenn.
      La liga al codigo es: https://github.com/oscarjb1/books-reactiveprogramming/blob/Capitulo-16-Produccion/api/api.js
      La liga a mi libro es: https://reactiveprogramming.io/books/applicaciones-reactivas-con-react-nodejs-mongodb
      saludos

  4. Buenas noche Oscar. Quer铆a consultar cual es la herramienta gr谩fica que usas en la imagen para ver el token. donde colocas la ruta y los datos. gracias.

    1. Hola Nestor, la herramienta es Restlet, que en realidad es un plugin de chrome, muy bueno, tiene versi贸n free y de paga, todo depende que tantas cosas requieras.
      saludos.

Deja un comentario

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *