vuex empty state on logout
Asked Answered
B

4

10

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?

Breazeale answered 29/3, 2018 at 5:24 Comment(2)
any updates on this?Africah
@DenysKotsur Not really, my solution was to store the start state and call replaceState(start_state), but this isn't such a great solutionBreazeale
L
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.

Luttrell answered 26/5, 2019 at 17:35 Comment(5)
This solution doesn't work for me. In reset state mutation, the value of the state for each module is not the initial value, but the last snapshot of it.Alleviate
could you try state[key] = JSON.parse(JSON.stringify(value.state))Luttrell
My final solution was based on another popular answer on SO. https://mcmap.net/q/204171/-how-to-clear-state-in-vuex-storeAlleviate
that surely helpsLuttrell
Good answer. Object.assign() must be used to maintain reactivity.Jagannath
T
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.

Towpath answered 29/3, 2018 at 6:31 Comment(3)
So how does this empty all the state ( as in all state in all modules)?Breazeale
@Breazeale So you can do a replaceState API call as this.$store.replaceState({});. This will clear state with empty object. Link - vuex.vuejs.org/en/api.htmlTowpath
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.Towpath
S
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");
  }
Saurel answered 4/2, 2021 at 18:10 Comment(0)
I
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

Irrevocable answered 5/5, 2021 at 13:38 Comment(3)
That works if you're using vuex-persist (And I do that in one of my newer applications). But that won't empty the state in a normal vuex store.Breazeale
@Breazeale thanks, is it a good practice for logout functionality especially when using vuex-persist in almost everything in the appIrrevocable
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').Breazeale

© 2022 - 2024 — McMap. All rights reserved.