I'm using Vuex and Axios to authenticate. I want to stay logged in when refreshing the browser using localStorage (yes, I know it's not the most secure solution). To get the user from the api, I use an async action in the vuex auth file.
If the user is not logged in, he can only see the signin page (SPA). To see if the user is logged in I used a
router.beforeEach()=>{if(!store.getters['auth/authenticated'])...}
. Every time I refresh the axios request is send, but the sign-in page doesn't wait for the response to show. I watched a youtube tutorial and for I can see, I did everything the same. Below you see the console logs.
How can I set that the router waits for the axios response and the SET_USER mutation?
Here is my Vue main file where I want to see if the user is logged in:
store.dispatch('auth/attempt', localStorage.getItem('token')).then(
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
)
the attempt action in the vuex auth module:
async attempt({ commit }, token) {
console.log('ACTION ATTEMPT: SET_TOKEN', token)
commit('SET_TOKEN', token)
try {
console.log('AXIOS CALL: to auth/me')
let response = await axios.get('auth/me');
console.log('AXIOS RESPONSE: response.data', response.data)
commit('SET_USER', response.data)
console.log('AXIOS: SET_USER', response.data)
} catch (error) {
console.log('error')
commit('SET_TOKEN', null)
commit('SET_USER', null)
}
}
the mutations:
mutations: {
SET_TOKEN(state, token) {
state.token = token
console.log('MUTATION: SET_TOKEN in mutation', state.token)
},
SET_USER(state, user) {
state.user = user
console.log('MUTATION: SET_USER in mutation', state.user)
}
},
the subscriber file to enable headers and localstorage:
store.subscribe((mutation) => {
switch (mutation.type) {
case 'auth/SET_TOKEN':
if (mutation.payload) {
axios.defaults.headers.common['Authorization'] = `Bearer ${mutation.payload}`
localStorage.setItem('token', mutation.payload)
} else {
axios.defaults.headers.common['Authorization'] = null
localStorage.removeItem('token')
}
break;
}
})
Getters:
getters: {
authenticated(state) {
console.log('SIGN-IN: authenticated token', state.token)
console.log('SIGN-IN: authenticated user', state.user)
return state.token && state.user
},
user(state) {
return state.user
}
},
The Vue Router:
Vue.use(VueRouter)
const routes = [
{ path: "*", component: PageNotFound },
{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: true,
},
},
{
path: '/signin',
name: 'signin',
component: signin,
beforeEnter: (to, from, next) => {
console.log('try to signin', store.getters['auth/authenticated']);
if (!store.getters['auth/authenticated']) {
return next()
}
else return next('');
}
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach((to, from, next) => {
// console.log('store.authenticated',store.getters['auth/authenticated'])
if (to.meta.requiresAuth && !store.getters['auth/authenticated']) {
next('signin');
}
else next();
// next();
})
export default router
- ACTION: ATTEMPT is the action which is called from the main.js
- MUTATION: SET_TOKEN is the mutation called first in the action
- AXIOS: CALL is the axios call to the api
- SIGN-IN: is the call to the getters from the sign-in route
- AXIOS: RESPONSE is the axios response
- MUTATION: SET_USER is the mutation called after the axios request is done
- AXIOS: SET_USER is when the user is set after the axios response.