Agregando JWT a Vuejs

Kevin Mendez
8 min readSep 8, 2019

--

Esta es una guía de continuación de nuestra publicación anterior de vuejs y JWT

Ya hemos tenido una introducción sobre vuejs y jwt. Así que ahora iremos al grano, sin antes no responder algunas posibles preguntas que yo me hacia al momento de iniciar con vue y jwt

Si eres un novato, y es primera vez que vas a usar jwt desde frontend, te recomiendo la siguiente lectura, si no, pasa directamente a la explicación

  • ¿Es necesario enviar siempre el token al servidor desde vue?
  • ¿Cómo sé yo que usuario está logeado tanto en backend como en frontend?
  • ¿Qué pasa cuando nuestra sesión expira?
  • ¿y el tiempo de concesión de vida del tokens?

Empecemos con lo básico, respondiendo la primera pregunta..

En realidad sí, ten en cuenta que siempre que uses jwt con cualquier tecnología / framework de javascript, el servidor si y solo sí, te solicitará verififcación mediante tokens a todas aquellas rutas que lo requieran; pongamos un ejemplo, nosotros ya hemos creado nuestra api el laravel, y hasta el momento solo configuramos las rutas con un midleware de jwt; pero no siempre serán a todas.

Supongamos que tenemos 4 rutas, una de login, otra de register, una de logout, y otra que obtiene los blogs; el servidor te solicitará el tokens cada vez que hagas una peticion http a toda aquella ruta que en el servidor esté configurada con jwt, es decir, nosotros en frontend no vamos a complicarnos con esto, enviaremos una petición, si existe el tokens lo enviamos, y si no, la petición siempre se hará, a que rutas enviaremos el tokens, esta definido en el backend. Ten eso siempre en cuenta, para evitar posibles confusiones.

¿El login necesita tokens? pues no, en este caso el login no necesita que exista un tokens en frontend porque no tiene sentido que el servidor nos esté pidiendo un tokens que él aún no ha solicitado, entonces, la petición llegara al servidor, el servidor nos logeara, nos devolverá el tokens, lo recibimos y almacenamos en el front. Es así de sencillo, no requiere de nada más.

¿El register necesita tokens? El mismo cuento que el login, no tiene sentido que el register nos esté solicitando un tokens que él no ha generado.

¿El logout y los blogs necesita tokens? En esté caso sí, debido a que estas rutas si están configuradas en el backend para que nos pida un tokens ya generado por nuestro servidor. Al momento de hacer logout nos lo pedirá pero por qué: esto es debido a que el único que puede hacer logout es ya un usuario logeado, es simplemente por lógica que lo tiene que solicitar para poder destruir la sesión en el backend; y el de blogs, es el mismo cuento, debido a que solo los usuarios logeado pueden ver los blogs publicados, al no ser que quieras que los blogs creados por usuarios sea accesible a cualquier persona que visite nuestro sitio web, en ese caso, como no es necesario que este un usuario logeado, no será necesario el envio de tokens cada vez que alguien desee ver nuestras publicaciones.

  • ¿Cómo sé yo que usuario está logeado tanto en backend como en frontend?

El frontend está conectado con el backend, el front realiza las peticiones al backend, y éste responde con la información solicitada, y es aquí cuando se verifica si un usuario esta logeado, ¿cómo lo hace? lo que realmente sucede es que el backend verifica un hash generado por el mismo, que está recibiendo desde nuestro app frontend. Si esté tokens ha experido el servidor nos devolvera un error http 403, nosotros en frontend capturamos este error, (Puede ser cualquier otro, dependiendo la configuración hecha en el backend); y así saber cuando ha caducado una sesión, y realizar lo que les sea conveniente, como redireccionar al login por ejemplo, o tomar este tokens expirado y renovarlo.

  • ¿Qué pasa cuando nuestra sesión expira?

Hay dos cosas que pueden pasar al momento que el tokens ha expirado:

1- Finalizar la sesión del usuario logeado

2- Restablecer la sesión para mantener siempre logeado nuestro usuario

  • ¿y el tiempo de concesión de vida del tokens?

Esto siempre será gestionado desde el backend; y dependerá de la configuración que hayamos establecido en el backend.

Ahora es posible que te preguntes que si por qué traigo esto a cuenta; pero es simplemente para aclarar que estás cosas no nos debe de preocupar en nuestro frontend, porque son tareas que son realizadas desde el servidor; y nuestra única responsabilidad es enviar el tokens, una vez lo tengamos disponible. Sabiendo esto, nos evitarnos algunos dolores de cabeza.

Empecemos creando un nuevo proyecto de vue.

Puede seguir está guía por si aún no estás familiarizado con vue-cli

Instalamos las siguiente librerias

  1. npm i bootstrap jquery popper.js
  2. npm i axios
  3. Añadir a src/main.ts: import 'bootstrap'; import 'bootstrap/dist/css/bootstrap.min.css';
  4. Añadir vuex-class npm install vuex-class

Con estas librerías, ya estamos listos para empezar a codificar las vistas.

Creamos las siguientes vistas dentro de la carpeta src/views

Empezaremos agregando las vistas

Agregando la vista más sencilla, la de about

Agregando la vista login

¿Qué es lo que hacemos en esta vista realmente?

Aparte de mostrar el html principal, lo que hacemos es generar una acción haciendo uso de los módulos de vuex, con TypeScript (ya antes explique cómo funcionan los módulos vuex)

Lo mismo se hace con la vista de register.

ya hemos agregado las vistas para login y register, luego, temporalmente, con código quemado, mostraremos un home

Ten en cuenta que será temporal, mas adelante, agregaremos contenido dinámico con datos desde nuestra api

¿Qué hace el blogContent? temporalmente, solo es código html quemado con la información de cada blogs.

Agregamos el component para el navbar

Lo que hace es sencillo, ya que solo toma el token almacenado en localStorage como booleano, y dependiendo del valor, si es verdadero o falso, muestra un menú correspondiente de si, el usuario está o no logeado.

Ya tenemos las vistas principales, ahora, vemos el código.

Como antes mencioné, esto funciona con typescript, lo hago así, para aprovechar las características que nos brinda typescript al momento de un tipado para javascript, aunque ten en cuenta, que no vamos a ser estrictos en este aspecto, ya que solo nos centramos en como usar jwt desde vue.

Agregamos 3 archivos desde el store de vuex, creamos dentro de la carpeta store/ una carpeta llamada module, types, e interfaces

dentro de la carpeta module, ira el modulo que se encargara del login, logout, y obtener el usuario logeado; y la carpeta types, será de donde obtengamos las variables para usarlas desde cualquier vista, y poder usar las actios, getters y mutations de authModule. la carpeta, interfaces, será el que contiene la información del State del modulo.

Creamos un archivo llamado authModule dentro de la carpeta store/module El modulo nos quedara de la siguiente manera.

Aquí se hacen todas las peticiones http, aprovechamos las ventajas de las promises de JS, y hacemos las peticiones al servidor, guardamos los datos, y mostramos en el frontend.

¿Puedes ver ese { http }?

Pues ese archivo es quien hace la magia para nuestra peticiones axios, ese archivo es quien almacena y envía nuestro token generado desde nuestro server. (En realidad no es que lo almacene, sino que lo toma del localStorage, cada vez que hacemos una nueva petición al server)

El código es el siguiente:

Lo que hacemos es lo siguiente:

1 - creamos una constante url y una constante http, si podemos ver, dentro de la constante http

2 - almacenamos la baseURL que nos ayuda a evitar poner la url completa en cada actions de nuestros módulos; por si aun no comprendes, te lo explico de esta manera:

cuando hacemos un axios.get(‘url/api/home’) donde url es la url a la que haremos la petición, entonces, la baseURL lo que hace se evitarnos que tener que poner esa url en cada petición que necesitemos hacer, quedándonos de la siguiente manera

axios.get(‘api/home’) 

¿Ves como nos ayuda este pequeño código?

Ahora los headers, básicamente es lo mismo, la constante http ya contiene los header que tenemos que enviar a nuestro server, en este caso, solo el autorizathion requerido por nuestro server laravel. Pueden haber la cantidad de headers necesarios, los que tú necesites.

Luego allí mismo, hacemos uso de los interceptores, ¿pero, para qué nos sirve? lo que los interceptores de axios hace, es capturar errores desde nuestro servidor a nivel global, a lo que me refiero es que puede haber un error 400, y capturarlo de manera global, y no necesariamente desde la peticion que lo genera.

Los interceptores son muy útiles cuando queremos hacer una acción como la de mostrar un loading en cada peticion http. (Lo veremos más adelante)

Luego, solo exportamos la constante http y URL; y la capturamos desde nuestro modulo authModule.

Luego, siempre en el archivo authModule, expotamos otras varibles como el State de la interface de typescript, y exportamos las constantes types.

¿Qué va dentro de estos dos archivos?

Dentro de la carpeta store/types creamos un archivos llamado authTypes.ts con el siguiente codigo

export default {mutations: {      SETUSER: ‘SETUSER’,},getters: {      GETUSER: ‘GETUSER’,},actions: {      LOGINUSER: ‘LOGINUSER’,
LOGOUTUSER: ‘LOGOUTUSER’,
REGISTERUSER: ‘REGISTERUSER’,
}};

A lo que nos ayuda este archivo es que podemos hacer uso de estas constantes desde cualquier lugar de nuestra aplicación, sin restricción de tipo de archivo, es decir, podemos usarlo tanto dentro de una vista, un componente, o un archivo .ts

Luego dentro de la carpeta /store/interfaces agregamos las siguientes lineas de código

export interface State {
user: Object,
token: Boolean
}

Observa que este archivo, contiene el tipo de datos que requerimos en el State del modulo authModule; es decir, que si queremos usar por ejemplo, userLoged en el modulo authModule, tenemos que ponerlo en forma de objeto, indicando qué tipo de datos tiene que ser. Así mismo, vsCode nos ayudará indicando que necesitamos establecer en el state del modulo el nuevo tipo de datos userLoged.

Por ultimo, necesitamos hacer unas modificaciones en nuestras rutas para lograr bloquear las rutas que queramos en el frontend, a qué me refiero? es cuando necesitamos ingresar a nuestra ruta principal, pero ésta está protegida mediante jwt en el backend; necesitamos que esta ruta, no este disponible para el usuario sin antes iniciar sesión.

Por si tienes algunas dudas, te recomiendo que eches una leída a la documentación oficial para router de vue

En este archivo, explicaré solo las siguientes lineas de código

router.beforeEach((to, from, next) => {   document.title = to.meta.title;
if (to.meta.Auth && !window.localStorage.getItem(‘_token’)) {
next({ path: ‘/login’ });
} else {
next();
}
});

Este fragmento de código es muy, pero que muy importante a la hora de crear un login con vue js, porque este interceptor, se ejecuta cada vez que entramos en cualquier URL establecida en nuestra app, es decir, que si iniciamos en /login, se ejecuta este fragmento de código, y si entramos en /register o /home o / siempre se ejecuta, entonces es aquí donde hacemos las verificaciones del token

El if, lo que hace es: verifica si la ruta a la que vamos a entrar, necesita autenticación, y si necesita tener un token; token que guardamos dentro del localStorage al momento de iniciar sesión o registrarnos en la aplicación (Puedes guardarlo donde mejor te sea conveniente)

Básicamente ya tenemos un login, register y logout con vue y laravel.

Te recomiendo que revises el código en github por si tienes dudas de implementación,

¿Qué paso con los blogs? pues eso lo dejamos para otro artículo, este ya se nos hizo un poco extenso.

No olvides dejarnos un comentario y compartir.

--

--

Kevin Mendez
Kevin Mendez

Written by Kevin Mendez

FullStack developers con Vuejs y Laravel. Apasionado por las nuevas tendencias tecnológicas.

Responses (1)