×


Authentication In Vue Using Vuex

Are you trying to figure out more about Authentication In Vue Using Vuex?

This guide is for 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.

Vuex manages states for Vue.js applications. It 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.

Here at Ibmi Media, as part of our Server Management Services, we regularly help our Customers to resolve Vuex queries.

In this context, we shall look into how to perform Authentication In Vue Using Vuex.


Authentication In Vue Using Vuex ?

In order to begin, you need to have the following:

i. Node on the local system.

ii. Knowledge of JavaScript and Vue.

iii. Vue CLI on the local system.


How to set up the application modules ?

Here, we will create a Vue application that has Vuex and vue-router.

In order to set it up, we run:

$ vue create vue-auth

In the dialogue box, we add the necessary information and select the options we need and complete the installation.


Moving ahead, we install Axios:

$ npm install axios –save


How to set up Axios ?

i. We need Axios across many of our components.

Open the ./src/main.js file and add the following:

[…]
import store from ‘./store’
import Axios from ‘axios’
Vue.prototype.$http = Axios;
const token = localStorage.getItem(‘token’)
if (token) {
Vue.prototype.$http.defaults.headers.common[‘Authorization’] = token
}
[…]

ii. Now, to use Axios inside our component, we can do this.$http.


How to set up Components ?

Do the following to set up the components.


1. The Login Component

i. Create a file Login.vue in the ./src/components directory.

Then, add the template for the login page:

<template>
<div>
<form class=”login” @submit.prevent=”login”>
<h1>Sign in</h1>
<label>Email</label>
<input required v-model=”email” type=”email” placeholder=”Name”/>
<label>Password</label>
<input required v-model=”password” type=”password” placeholder=”Password”/>
<hr/>
<button type=”submit”>Login</button>
</form>
</div>
</template>

ii. Once done, we add the data attributes that would bind to the HTML form:

[…]
<script>
export default {
data(){
return {
email : “”,
password : “”
}
},
}
</script>

iii. Now, let us add the method for handling login:

[…]
<script>
export default {
[…]
methods: {
login: function () {
let email = this.email
let password = this.password
this.$store.dispatch(‘login’, { email, password })
.then(() => this.$router.push(‘/’))
.catch(err => console.log(err))
}
}
}
</script>

We are using a vuex action – login to handle this authentication.


2. The Register Component

i. This component is to register users.

We begin by creating a file Register.vue in the components directory and add the following:

<template>
<div>
<h4>Register</h4>
<form @submit.prevent=”register”>
<label for=”name”>Name</label>
<div>
<input id=”name” type=”text” v-model=”name” required autofocus>
</div>
<label for=”email” >E-Mail Address</label>
<div>
<input id=”email” type=”email” v-model=”email” required>
</div>
<label for=”password”>Password</label>
<div>
<input id=”password” type=”password” v-model=”password” required>
</div>
<label for=”password-confirm”>Confirm Password</label>
<div>
<input id=”password-confirm” type=”password” v-model=”password_confirmation” required>
</div>
<div>
<button type=”submit”>Register</button>
</div>
</form>
</div>
</template>

ii. Let us define the data attributes we will bind to the form:

[…]
<script>
export default {
data(){
return {
name : “”,
email : “”,
password : “”,
password_confirmation : “”,
is_admin : null
}
},
}
</script>

iii. Then, we add the method for handling login:

[…]
<script>
export default {
[…]
methods: {
register: function () {
let data = {
name: this.name,
email: this.email,
password: this.password,
is_admin: this.is_admin
}
this.$store.dispatch(‘register’, data)
.then(() => this.$router.push(‘/’))
.catch(err => console.log(err))
}
}
}
</script>

3. The Secure Component

This will only display if our user is authenticated. We create the component file, Secure.vue, and add the following:

<template>
<div>
<h1>This page is protected by auth</h1>
</div>
</template>


How to Update The App Component ?

i. Initially, we open ./src/App.vue file and add the following:

<template>
<div id=”app”>
<div id=”nav”>
<router-link to=”/”>Home</router-link> |
<router-link to=”/about”>About</router-link><span v-if=”isLoggedIn”> | <a @click=”logout”>Logout</a></span>
</div>
<router-view/>
</div>
</template>

ii. Now, we will add the logic behind the log out:

<script>
export default {
computed : {
isLoggedIn : function(){ return this.$store.getters.isLoggedIn}
},
methods: {
logout: function () {
this.$store.dispatch(‘logout’)
.then(() => {
this.$router.push(‘/login’)
})
}
},
}
</script>

Here, we did two things; compute the authentication state of the user and dispatch a logout action to our Vuex store when a user clicks the logout button. 


iii. After the logout, we send the user to the login page using this.$router.push(‘/login’).


How to set up Vuex Auth Module ?

First, we will set up the store.js file for vuex:

import Vue from ‘vue’
import Vuex from ‘vuex’
import axios from ‘axios’
Vue.use(Vuex)
export default new Vuex.Store({
state: {
status: ”,
token: localStorage.getItem(‘token’) || ”,
user : {}
},
mutations: {
},
actions: {
},
getters : {
}
})

We have now defined the attributes of the state.

Now the Vuex state will hold our authentication status, jwt token, and user information.


How to Create The Vuex login Action ?

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:

login({commit}, user){
return new Promise((resolve, reject) => {
commit(‘auth_request’)
axios({url: ‘http://localhost:3000/login’, data: user, method: ‘POST’ })
.then(resp => {
const token = resp.data.token
const user = resp.data.user
localStorage.setItem(‘token’, token)
axios.defaults.headers.common[‘Authorization’] = token
commit(‘auth_success’, token, user)
resolve(resp)
})
.catch(err => {
commit(‘auth_error’)
localStorage.removeItem(‘token’)
reject(err)
})
})
},

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.

To ensure we allow the user to return to the application within the validity time of the token and not have to log in again, we have to keep the token in localStorage.

We return a promise so we can return a response to a user after login is complete.


How to Create The Vuex register Action ?

The register action works almost similar to the login action. In the same file, we add the following:

register({commit}, user){
return new Promise((resolve, reject) => {
commit(‘auth_request’)
axios({url: ‘http://localhost:3000/register’, data: user, method: ‘POST’ })
.then(resp => {
const token = resp.data.token
const user = resp.data.user
localStorage.setItem(‘token’, token)
axios.defaults.headers.common[‘Authorization’] = token
commit(‘auth_success’, token, user)
resolve(resp)
})
.catch(err => {
commit(‘auth_error’, err)
localStorage.removeItem(‘token’)
reject(err)
})
})
},


How to Create The Vuex logout Action ?

For the user to have the ability to log out of the system, we destroy all data created during the last authenticated session. 

In the object of the same action, we add the following:

logout({commit}){
return new Promise((resolve, reject) => {
commit(‘logout’)
localStorage.removeItem(‘token’)
delete axios.defaults.headers.common[‘Authorization’]
resolve()
})
}

Now, when the user clicks to log out, we remove the jwt token.

There is no way they can perform a transaction requiring a token now.


How to Create The Mutations ?

We use Mutators to change the state of a Vuex store. 

In the mutators object, we add:

mutations: {
auth_request(state){
state.status = ‘loading’
},
auth_success(state, token, user){
state.status = ‘success’
state.token = token
state.user = user
},
auth_error(state){
state.status = ‘error’
},
logout(state){
state.status = ”
state.token = ”
},
},


How to Create The Getters ?

We use getter to get the value of the attributes of the Vuex state. 

The role of our getter in the situation is to separate application data from application logic and ensure we do not give away sensitive information.

Add the following to the getters object:

getters : {
isLoggedIn: state => !!state.token,
authStatus: state => state.status,
}

You would agree with me that this is a neater way to access data in the store.


How to Hide Pages Behind Auth ?

Our whole purpose is to implement authentication and keep pages away from unauthorized access.

For this, we need to have a track of the page the user wants to visit. Meanwhile, we need to check if the user has access or not.

In addition, we need a way to say if the page is reserved for only authenticated users or unauthenticated users, or both.

We can achieve these important considerations with Vue-router.


How to Define Routes For Authenticated And Unauthenticated Pages ?

Initially, open the ./src/router.js file and import things we need for the setup:

import Vue from ‘vue’
import Router from ‘vue-router’
import store from ‘./store.js’
import Home from ‘./views/Home.vue’
import About from ‘./views/About.vue’
import Login from ‘./components/Login.vue’
import Secure from ‘./components/Secure.vue’
import Register from ‘./components/Register.vue’
Vue.use(Router)

As you can see, right now we have vue, Vue-router, and our Vuex store setup.

Let us now define the routes:

[…]
let router = new Router({
mode: ‘history’,
routes: [
{
path: ‘/’,
name: ‘home’,
component: Home
},
{
path: ‘/login’,
name: ‘login’,
component: Login
},
{
path: ‘/register’,
name: ‘register’,
component: Register
},
{
path: ‘/secure’,
name: ‘secure’,
component: Secure,
meta: {
requiresAuth: true
}
},
{
path: ‘/about’,
name: ‘about’,
component: About
}
]
})
export default router


How to Handle Unauthorized Access Cases ?

Moving ahead, let us check for unauthorized access and take action.


In the router.js file, add the following before the export default router:

router.beforeEach((to, from, next) => {
if(to.matched.some(record => record.meta.requiresAuth)) {
if (store.getters.isLoggedIn) {
next()
return
}
next(‘/login’)
} else {
next()
}
})

While using Vue router for authentication, we had a really complex mechanism. 

However, Vuex helps us simplify that completely. Hence, we can go on to add any condition to our route.


How to Handle Expired Token Cases ?

Since we store our token in localStorage, it remains there perpetually. In such a case, what happens at most is that our requests will fail because of an invalid token.


In order to solve this, we open ./src/App.vue file and in the script, add:

export default {
[…]
created: function () {
this.$http.interceptors.response.use(undefined, function (err) {
return new Promise(function (resolve, reject) {
if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
this.$store.dispatch(logout)
}
throw err;
});
});
}
}

Here, we are intercepting Axios call to determine if we get 401 Unauthorized response.

If yes, we dispatch the logout action and the user gets logged out of the application.


[Need urgent help with the Vue process? We can help you. ]


Conclusion

This article covers how to perform Authentication In Vue Using Vuex. 

Using Vuex allows us to store and manage authentication state and proceed to check state in our application using only a few lines of code.


To Set up the application modules:

For this project, we want to create a vue application that has vuex and vue-router. 

i. We will use the vue cli 3.0 to create a new vue project and select router and vuex from the options.

Run the following command to set it up:

$ vue create vue-auth

ii. Follow the dialogue that shows up, add the necessary information and select the options we need and complete the installation.

iii. Next, install axios:

$ npm install axios --save