jwt authentication with vuejs

Asked

Viewed 4,066 times

4

I’m a little confused with the authentication using jwt token, I have an application in vuejs + Vue-router, I don’t want to use vuex until I learn to do it without it (I don’t like to use what I don’t understand). Then I have my API in Nodejs that grants me a payload with token when the user logs in.

My question is, now I have this token, what do I do with it? I read several articles, said to store on site Torage(vulnerable to XSS), others on cookie(vulnerable to CSRF), but I don’t want to get too safe here, because I haven’t even made it work in any way. What I did was store in Storage location when I get the response with the server token like this.

in my main.js is like this:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'

axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.headers.common['Authorization'] = "Bearer" + localStorage.getItem('jwtToken')

Vue.use(VueAxios, axios)

router.beforeEach((to, from, next) => {
    if (to.meta.requiresAuth) {
        if (**O QUE COLOCO AQUI SEM UTILIZAR O VUEX?**) {
            next() 
        } else {
            next('/')
        }
    } else {
        next()
    }
})

new Vue({
  el: '#app',
  router,
  axios,
  render: h => h(App)
})

Where "to.meta.requiresAuth" means: routes that have the "meta.requiresAuth = true" element will be intercepted by logic within if.

You can see that I don’t know what verification to do, I could actually verify the existence or not of the token at the Torage site, but I believe that just checking the existence or not would be very insecure. Since you could say that you have the token and it has not yet been received by the server. But if I do this, the way I thought would be to send a post to the server and validate the token, if it is valid, then next(), if it is not redirected to the home. But I don’t know if it’s the proper way to deal with this problem. I’m kind of lost.

  • Cara I think both means of authentication will have authentication problems, but generally, even more in Vuejs I usually save the jwt token in the same localStorage and create an Axios Interceptor that checks in each request, if the token is valid, and I don’t do that check on the route itself. On routes I usually leave to deal only if it has the token in the localStorage or not. If you wish, I can give you an answer with explanation and the code of what I’m talking about. I’m commenting because it’s not exactly what you want from what I understand.

  • It’s what I saw here, that’s right, on the routes in the client release only if the token exists, and when you need to order something in the backend api, then validate the token, if not valid, send the 401, so that the client redirects to home. It would be a good thing to answer the question, if you have time.

1 answer

4


In this case, as I said in the comments, I usually save the JWT token in the Torage locale. First of all about route blocking, I usually block any and all requests by creating one interceptor in Asia. For this, you can create a js file such as a http.js that controls requests and intercepts them by checking whether the user has a valid token or not, which will eventually export an instance of Axios. Goes below:

http.js

import axios from 'axios'

let api = 'http://localhost:8080/api/'

const http = axios.create({
  baseURL: api
})

http.interceptors.request.use((config) => {
  const token = localStorage.getItem('user-token')

  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }

  return config
}, (err) => {
  return Promise.reject(err)
})

http.interceptors.response.use((response) => {
  return response
}, (error) => {
  if (error.response.status === 401) {
    window.location = '#/home'
  }

  return Promise.reject(error)
})

export default http

Basically in each request, it will go through the method interceptors.request and check if you have the token previously, and otherwise you will return an error directly, without actually reaching the back end. The same will occur in the case of the answer, and as you said if it is not valid (401), the user is redirected to the home. To use it, it can be imported globally into your main.js or per component.

Talking about locking directly on the routes of your application, ie when going through your router, I usually do it in two ways:

To stop only one route:

routes: [
    {
      path: '/',
      name: 'home',
      beforeEnter: function (to, from, next) {
        const token = localStorage.getItem('user-token')

        if (!token) {
          next('/login')
        } else {
          next()
        }
      },
      component: require('@/components/Home').default
    },
  ]

In this case it is checking the token before entering the route, and if it does not exist, the user is redirected to the login.

To stop all routes

router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('user-token')

  if (!token) {    
    next('/login')
    return;
  }

  next();
});

Same working though will check on all routes, and if the token does not exist, will redirect to login. In this case it must have a constant Routes obligatorily, with all its routes inside.

const router = new Router({
  routes: []
});

I hope I’ve helped.

  • Just one more question, and how you implement the sharing of this logged in or not logged in state between the components?

  • So, for this in my opinion the best way is using Vuex itself, where when logging in you will trigger an action for a Login Store or User, where you will make the authentication request. With the answer, it will trigger a Mutation that in turn will save in a state. Using mapState on each component, a computed property, you will have access to the logged-in user. I didn’t say anything because you didn’t want to use Vuex rs.

  • yes, but I ended up reading his doc and using kkkk but I noticed a problem, if I update the page vuex restarts the values of "state", how do you get around it? I’m going around like this in my main.js: if (localStorage.getItem('jwtToken')) {
 store.commit('setIsLogged', true)
}

  • Yes, every time you update you lose the data. I structure my application for in the first component that is created ("parent"), whatever owns the router-view of the whole application, I placed to make the request of the user data logged in created(), so every time F5 occurs (screen update), always first make the request, and all components that will always be called after it, possessing the data logged. localStorage doesn’t need to be inside the Store either necessarily, and it doesn’t get lost in the screen update.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.