Ver contenido

carlosazaustre.es carlosazaustre.es

Cómo implementar autenticación basada en token con Node.js

🗓 | 💻 Desarrollo | 🕐 3 minutos de lectura | 💬 Comments

En el anterior post vimos las bases de la autenticación basada en token en una aplicación web. En este post, vamos a ver como implementar este tipo de autenticación en un servidor usando Node.js

Voy a separar las funciones en varios archivos, siguiendo buenas prácticas y modularizando dependendiendo de la funcionalidad.

Nuestro servidor en Node.js

Lo primero es crear el archivo server.js dónde configuramos Express (en versión 4), importamos los módulos necesarios y hacemos correr el servidor y la base de datos.

Si te pierdes un poco, en éste post anterior expliqué como crear un API REST en Node.js con Express y MongoDB. Y si prefieres también tengo un videotutorial en YouTube sobre el tema.

Configuración básica de un servidor en Node.js utilizando Express v4.

Simplemente hemos importado los módulos necesarios y la configuración básica de Express. También he importado un archivo con el Schema del modelo User donde almacenaremos nuestros usuarios. Las rutas que utilizaremos serán /auth/signup para el registro con email y contraseña y /auth/login para autenticarnos.

Luego tendremos una ruta adicional, /private que sólo podremos acceder a ella si estamos logueados. Si nos fijamos, he creado un middleware para esta última ruta, que se ejecutará antes de la función controladora. Lo he separado en un módulo aparte, de esta manera podemos reutilizar esta función en todas las rutas que queramos que sean privadas.

De igual manera, en las funciones controladores de /auth/signup y /auth/login utilizo otras funciones importadas como son auth.emailSignup y auth.emailLogin que definiremos a continuación.

Controladores

En el fichero auth.js voy a definir las dos funciones controladoras para el registro y autenticación de usuarios.

En emailSignup creo un nuevo usuario, con los campos que estimemos necesarios para nuestra aplicación, por ejemplo el email, nombre, contraseña, etc... Despues de salvar el usuario, enviamos un código 200 de OK en la respuesta, junto con un mensaje en el que pasaremos el token que creamos en la función service.createToken() que veremos a continuación.

Para el emailLogin, buscamos primero si el usuario existe y comprobamos que la contraseña es correcta o no. Si todo es OK, volvemos a enviar un código 200 en la respuesta HTTP junto con el token.

Codificando el JSON Web Token

Ahora vamos al "meollo" de este artículo, la creación de un Token que identifique a nuestro usuario en cada petición HTTP que realice.

Para codificar el token utilizamos una clave secreta. Es importante que esta clave permanezca lo más oculta posible. Una opción es almacenarla en un fichero config.js y ese fichero no subirlo al repositorio con .gitignore o la opción mejor es utilizar una variable de entorno (con process.env) que esté en nuestro servidor, y otra para nuestro entorno de desarrollo.

Sería algo así:

Cuando importemos el fichero config.js en la variable TOKEN_SECRET tendremos nuestra clave para codificar.

Creamos el servicio que utilizaremos para codificar el token. Para ello vamos utilizar la librería jwt-simple que nos facilita la vida a la hora de codificar el payload y hace todo el trabajo que expliqué en el post anterior.

Creamos un objeto payload en el que ponemos tres atributos: sub, iat y exp. Que ya explicamos anteriormente. En sub almacenamos el ID del usuario que pasamos por parámetro.

También usamos la librería moment para ayudarnos en el manejo de fechas. Con moment().unix() conseguimos el tiempo actual en formato UNIX, y con moment().add(14, "days").unix() le estamos añadiendo 14 días al momento actual. Muy útil para establecer una fecha de creación y expiración.

Por úlitmo devolvemos el JSON Web Token, codificando el payload con nuestra clave secreta.

Acesso a rutas con autenticación.

Cada vez que accedamos a una ruta privada, sólo accesible si estamos autenticados, como por ejemplo /private, le pasamos el middleware ensureAuthenticated que a continuación programaremos:

Lo primero que hacemos en la función es comprobar que la petición, req lleva la cabecera de autorización req.headers.authorization. Ésto lo envía el Frontend y lo veremos en un próximo post, con Angular.js

Si la petición no envía una autorización, envíamos el código de error 403 de acesso denegado. y si no, tomamos el token.

la cabecera, tendrá una pinta parecida a ésta:

Sólo tenemos que obtener el token de ese String y lo hacemos con el método split de JavaScript:

Decodificamos ese token con la función decode y la clave secreta y ya podemos identificar al usuario, con el atributo sub del objeto payload, que según este ejemplo serán un ObjectID de Mongo.

En la próxima entrada, veremos cómo programar la autenticación en la parte del cliente con Angular.js.

✎ ¿Ves alguna errata? ¿Quieres modificar algo? Haz una Pull Request.

Carlos Azaustre

Soy Carlos Azaustre. Me dedico al desarrollo web. Actualmente trabajo como Senior Frontend Engineer en Eventbrite. Fui nombrado en 2019 GDE (Google Developer Expert) en Tecnologías Web. Desde 2013 intento documentar en éste blog todo lo que aprendo y así compartirlo con el resto de la comunidad.

Si te gusta lo que lees, puedes apoyarme en mi Patreon o invitarme a un café virtual 🙂

Se mi patrón Invítame a un Café