9

Quick story of my problem:

  1. Absolutely no data is stored in my vuex state when the page loads
  2. If the user is logged in(or has info stored in window.localStorage and therefore gets auto logged in) my vuex store retrieves all the info from a socket that requires authentication.
  3. Then the user logs out, But my vuex state save still retains all its data

This would be a security issue as not logged in people(or hackers) on a public pc could view what the state was before the user logged out.

I have seen How to clear state in vuex store? But I feel that this is a hack and should be avoided.

My current solution is just to refresh the page using location.reload();

Is there a better way to prevent this data leak?

DrevanTonder
  • 726
  • 2
  • 12
  • 32

4 Answers4

9

All objects stored in Vue act as an observable. So if the reference of a value is changed/mutated it triggers the actual value to be changed too.

So, In order to reset the state the initial store modules has to be copied as a value.

On logging out of a user, the same value has to be assigned for each module as a copy.

This can be achieved as follows:

// store.js

// Initial store with modules as an object
export const initialStoreModules = {
    user,
    recruitment,
};

export default new Vuex.Store({
    /**
     * Assign the modules to the store 
     * using lodash deepClone to avoid changing the initial store module values
     */
    modules: _.cloneDeep(initialStoreModules),
    mutations: {
        // reset default state modules by looping around the initialStoreModules
        resetState(state) {
        _.forOwn(initialStoreModules, (value, key) => {
            state[key] = _.cloneDeep(value.state);
        });
        },
    }
});

Then call commit("resetState"); when the user logs out.

DrevanTonder
  • 726
  • 2
  • 12
  • 32
Mukundhan
  • 3,284
  • 23
  • 36
1

Normal Approach

If user logs in, then you can add few boolean flags to ensure that user has been loggedin/loggedout.

So initial approach would be -

this.$store.commit('insertToken', {realtoken, isLoggedIn: true})

In vuex than,

insertToken (state, payload) {
  state.token = payload.realtoken
  state.isLoggedIn = payload.isLoggedIn
  localStorage.setItem('token', payload.realtoken)
}

And when user logs out you should set all flags to false, In component -

logout () {
    this.$store.commit('logOut')
    this.$router.replace('/login')
  }

and in vuex,

logOut (state, payload) {
  state.token = null
  state.isLoggedIn = false
  localStorage.setItem('token', null)
},

So by means of isLoggedIn and token you can tell router where to navigate by using term called Navigation Guards

Example -

const checkToken = () => {

if ((localStorage.getItem('token') == null) || 
 (localStorage.getItem('token') == undefined)) {
  return false
 } else {
   return true
 }
}

// Navigation guards
if (to.path === '/') {
 if (checkToken()) {
   next()
 } else {
  router.push('/login')
 }

}

This is the way I use when authentication is done by means of using token as part of interacting with Vuex.

Meet Zaveri
  • 2,921
  • 1
  • 22
  • 33
  • So how does this empty all the state ( as in all state in all modules)? – DrevanTonder Mar 29 '18 at 11:38
  • @DrevanTonder So you can do a `replaceState` API call as `this.$store.replaceState({});`. This will clear state with empty object. Link - https://vuex.vuejs.org/en/api.html – Meet Zaveri Mar 29 '18 at 13:20
  • Hmm. Well if there is interaction done with localStorage, then its sure this wouldn't help. I'll look up for possible solution. Meanwhile there are great devs on DISCORD community. You can share your problem with them. – Meet Zaveri Mar 29 '18 at 13:44
0

This extension does a nice job https://www.npmjs.com/package/vuex-extensions

With it installed I can just call reset in the Vuex Logout Action

logout(context) {
  
    // do the logout stuff, such as 
    context.commit("setUser", {});

    // On logout, clear all State, using vuex-extensions
    this.reset();

    // if using router, change to login page   
    router.replace("/login");
  }
Peter Kerr
  • 1,649
  • 22
  • 33
0

This might be late but I found window.localStorage.removeItem('vuex') useful. Thanks to Thomas von Deyen, https://github.com/championswimmer/vuex-persist/issues/52#issuecomment-413913598

Valentine Sean
  • 79
  • 3
  • 13
  • That works if you're using [vuex-persist](https://github.com/championswimmer/vuex-persist) (And I do that in one of my newer applications). But that won't empty the state in a normal vuex store. – DrevanTonder May 12 '21 at 11:02
  • @DrevanTonder thanks, is it a good practice for logout functionality especially when using vuex-persist in almost everything in the app – Valentine Sean May 13 '21 at 06:44
  • Well, it works, but since it's a hack to empty vuex I wouldn't call it a good practice. It's using vuex-persist to do something it's not intended for. But if you didn't want to store empty states in your store and store modules you could justify using `localStorage.removeItem('vuex')`. – DrevanTonder May 14 '21 at 01:18