Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auth not accessible in vuex-module after page reload or direct access

I have an authentication on my nuxt web-app, using the nuxt/auth module. I also use modular vuex stores to handle different states. After I login, everything is fine and I can navigate through the app normally. But when I try to reload the page or access it directly through a URL, the user is not accessible, thus, the whole web-app becomes unusable. I try to access the user object with this.context.rootState.auth.user, which is null after page-reload or direct access. Strangely enough, this only happens in production.

I already tried to add an if-guard, but sadly the getter is not reactive. Probably because it´s a nested object. This is my current getter:

 get someGetter() {
    if (!this.context.rootState.auth.user) {
      return []
    }
    const userId = this.context.rootState.auth.user.id as string
    const arr = []
    for (const item of this.items) {
        // Using userId to add something to arr
    }
    return arr
  }

Is there a way to force nuxt to finish the authentication before initialising the vuex-modules, or to make this getter reactive, so it will trigger again, when the user object is accessible?

This is what my auth-config looks like in nuxt.config.ts:

auth: {
  strategies: {
    local: {
      _scheme: '@/auth/local-scheme',
      endpoints: {
        login: {
          url: '/api/authenticate',
          method: 'post',
          propertyName: false
        },
        logout: { url: '/api/logout', method: 'post' },
        user: { url: '/api/users/profile', propertyName: false }
      }
    },
    // This dummy setting is required so we can extend the default local scheme
    dummy: {
      _scheme: 'local'
    }
  },
  redirect: {
    logout: '/login'
  }
}

EDIT

I resolved this by following Raihan Kabir´s answer. Using vuex-persistedstate in an auth-plugin, which is triggered every time the server renders the page. The plugin saves the userId in a cookie, so the store can use it as a fallback, if the auth-module isn´t ready.

like image 776
UdoLambada Avatar asked Feb 11 '20 07:02

UdoLambada


People also ask

Are you wondering about authentication in Vue using Vuex?

Wondering about Authentication In Vue Using Vuex? We can help you. We have seen customers use local storage to manage tokens generated through client-side authentication. Vuex serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

What is a Vuex module?

To help with that, Vuex allows us to divide our store into modules. Each module can contain its own state, mutations, actions, getters, and even nested modules - it's fractal all the way down: Inside a module's mutations and getters, the first argument received will be the module's local state.

What happens when a user leaves a Vuex application?

The login action passes the Vuex commit helper that we use to trigger mutations. We could store the token in vuex store, but if the user leaves our application, all of the data in the vuex store disappears.

How to commit mutations to the Vuex store?

We have now defined the attributes of the state. Now the Vuex state will hold our authentication status, jwt token, and user information. We use Vuex actions to commit mutations to the vuex store. To create a login action, we open the ./src/store.js file and add the following to the actions object:


1 Answers

The thing is, the vuex clears data on reload/refresh to keep credentials secure. That's what vuex is. If you want to store data for long time without being interrupted after reloading, you should use localstorage for that. But localstorage is not recommended for storing credentials.

If you need only user_id to keep in the vuex, use Cookie instead. And try something like this in your store's index.js file -

export const actions = {
    // This one runs on the beginning of reload/refresh
    nuxtServerInit ({ commit }, { req }) {
        if (req.headers.cookie) {
              const parsed = cookieparser.parse(req.headers.cookie)
              try {
                  // get user id that you would set on auth as Cookie
                  user_id = parsed.uid
              } catch (err) {
                  // error here...
              }
        }

        // perform login and store info on vuex store
        commit('authUserOnReload', user_id)
    },
}

// Define Mutations
export const mutations = {
    authUserOnReload (state, user_id) {
        // perform login here and store user
    }
}
like image 137
Raihan Kabir Avatar answered Sep 22 '22 16:09

Raihan Kabir