2

Im trying to create a plugin for manage the Oauth2 token data in my vuejs app.

I created the plugin following some few tutorials that are available on the internet.

var plugin = {}

plugin.install = function (Vue, options) {
  var authStorage = {
    getToken () {
      let token = localStorage.getItem('access_token')
      let expiration = localStorage.getItem('expiration')
      if (!token || !expiration) {
        return null
      }
      if (Date.now() > parseInt(expiration)) {
        this.destroyToken()
        return null
      }

      return token
    },
    setToken (accessToken, expiration, refreshToken) {
      localStorage.setItem('access_token', accessToken)
      localStorage.setItem('expiration', expiration + Date.now())
      localStorage.setItem('refresh_token', refreshToken)
    },
    destroyToken () {
      localStorage.removeItem('access_token')
      localStorage.removeItem('expiration')
      localStorage.removeItem('refresh_token')
    },
    isAuthenticated () {
      if (this.getToken()) {
        return true
      } else {
        return false
      }
    }
  }

  Vue.prototype.$authStorage = authStorage
}

export default plugin

but when a try to access the methods on the main.js file, i get error saying that the object is undefined.

import Vue from 'vue'
import App from './App'
import router from './router'
import AuthStorage from './AuthStorage.js'

Vue.config.productionTip = false
Vue.use(AuthStorage)

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requireAuth)) {
    if (!Vue.$authStorage.getToken()) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next()
  }
})
axios.defaults.headers.common = {
  'Authorization': `Bearer ${Vue.$authStorage.getToken()}`
}
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})

chrome console showing the error

Inside the components the plugin works as expected. The problem is when o try to use in the main.js file. I already tried with: this.$authStorage this.authStorage Vue.authStorage

no success

1 Answer 1

5

You are adding $authStorage to the prototype of Vue.

Vue.prototype.$authStorage = authStorage

That means will only be available on instances of the Vue object (ie. the result of new Vue(...).

If you want $authStorage to be available as a property of Vue without creating an instance, you need to add it as a static property.

Vue.$authStorage = authStorage

But, if it were me, I would probably take a different approach. I would likely build the AuthStorage plugin like this:

const authStorage = {
    getToken() {
      let token = localStorage.getItem('access_token')
      let expiration = localStorage.getItem('expiration')
      if (!token || !expiration) {
        return null
      }
      if (Date.now() > parseInt(expiration)) {
        this.destroyToken()
        return null
      }

      return token
    },
    setToken(accessToken, expiration, refreshToken) {
      localStorage.setItem('access_token', accessToken)
      localStorage.setItem('expiration', expiration + Date.now())
      localStorage.setItem('refresh_token', refreshToken)
    },
    destroyToken() {
      localStorage.removeItem('access_token')
      localStorage.removeItem('expiration')
      localStorage.removeItem('refresh_token')
    },
    isAuthenticated() {
      if (this.getToken()) {
        return true
      } else {
        return false
      }
    },
    install(Vue) {
      Vue.prototype.$authStorage = this
    }
}

export default authStorage

Which would allow me to use it like this outside of Vue,

import Vue from 'vue'
import App from './App'
import router from './router'
import AuthStorage from './AuthStorage.js'

Vue.config.productionTip = false
Vue.use(AuthStorage)

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requireAuth)) {
    if (!AuthStorage.getToken()) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next()
  }
})

And reference it like this inside of Vue:

created(){
  let token = this.$authStorage.getToken()
}

Here is an example.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.