简体   繁体   中英

How to store, manage REST API JWT authentication token in vue?

I am a noob, using vue.js and a node auth api, the api works fine and provides the jwt token in the response, my question is how can i use the token in all the requests that follows (using axios), and any best practices for handling the token in the front end is also appreciated.

Thanks

You can find here a lot of good patterns which I personally use on my projects and how also JWT token handling.

For saving token in a brower, you can use cookie, sessionStorage or localStorate, last one is the most popular now (short explination here ).

In a few words, you can create an axion instance and add a token before request sent.

const http = axios.create({
  baseURL: process.env.VUE_APP_SERVER_API,
  // here you can specify other params 
})

http.interceptors.request.use(request => {
  // Do something before request is sent
  request.headers['Authorization'] = `JWT ${TOKEN_HERE}`
  // some logic what to do if toke invalid, etc ...
  return request
}, function (error) {
  // Do something with request error
  return Promise.reject(error)
})

You can use something like that for Your scenario in your vuejs app.

import axios from 'axios'

const API_URL = 'http://localhost:3000'

const securedAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

const plainAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

securedAxiosInstance.interceptors.request.use(config => {
  const method = config.method.toUpperCase()
  if (method !== 'OPTIONS' && method !== 'GET') {
    config.headers = {
      ...config.headers,
      'X-CSRF-TOKEN': localStorage.csrf
    }
  }
  return config
})

securedAxiosInstance.interceptors.response.use(null, error => {
  if (
    error.response &&
    error.response.config &&
    error.response.status === 401
  ) {
    return plainAxiosInstance
      .post('/refresh', {}, { headers: { 'X-CSRF-TOKEN': localStorage.csrf } })
      .then(response => {
        localStorage.csrf = response.data.csrf
        localStorage.signedIn = true

        let retryConfig = error.response.config
        retryConfig.headers['X-CSRF-TOKEN'] = localStorage.csrf
        return plainAxiosInstance.request(retryConfig)
      })
      .catch(error => {
        delete localStorage.csrf
        delete localStorage.signedIn

        location.replace('/')
        return Promise.reject(error)
      })
  } else {
    return Promise.reject(error)
  }
})

export { securedAxiosInstance, plainAxiosInstance }

And in your component you use this to process your request with api

Products.vue

export default {
  name: 'products',
  data () {
    return {
      products: [],
      newProduct: [],
      error: '',
      editedProduct: ''
    }
  },
  created () {
    if (!localStorage.signedIn) {
      this.$router.replace('/')
    } else {
      this.$http.secured.get('/api/v1/products')
        .then(response => { this.products = response.data })
        .catch(error => this.setError(error, 'Something went wrong'))
    }
  },
  methods: {
    setError (error, text) {
      this.error = (error.response && error.response.data && error.response.data.error) || text
    },
    addProduct () {
      const value = this.newProduct
      if (!value) {
        return
      }
      this.$http.secured.post('/api/v1/products/', { product: { name: this.newProduct.name } })
        .then(response => {
          this.products.push(response.data)
          this.newProduct = ''
        })
        .catch(error => this.setError(error, 'Cannot create product'))
    },
    removeProduct (product) {
      this.$http.secured.delete(`/api/v1/products/${product.id}`)
        .then(response => {
          this.products.splice(this.products.indexOf(product), 1)
        })
        .catch(error => this.setError(error, 'Cannot delete product'))
    },
    editProduct (product) {
      this.editedproduct = product
    },
    updateProduct (product) {
      this.editedProduct = ''
      this.$http.secured.patch(`/api/v1/products/${product.id}`, { product: { title: product.name } })
        .catch(error => this.setError(error, 'Cannot update product'))
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM