Handling Vuex and Axios Authentication
In this tutorial, we will be using Vuex and Axios to handle simple authentication in our Vuejs app. The flow for implementing this is:
- User login using password and email ( fake login)
- On successful authentication, the user is granted access to specific resources.
Prerequisites
In the course of building this application, we would be using Vuex to manage our application state,
Vue router For navigation and Axios to fetch data from the API.
Sequel to the preceding, we should possess a basic knowledge of JavaScript and Vue to aid easy comprehension of the steps to be followed in this article.
We will also need Node.js for a Vue setup, so download and install it if you haven’t already.
Step 1 – Setting up the Vue project
Now let’s start by installing Vue CLI into our machine.
npm install -g @vue/cli
Vue CLI helps us to create and manage Vue projects from the command line.
To check if Vue CLI has been installed, run the following command on your terminal:
vue --version
We will Now use the Vue CLI to build a simple application. To do that open up your terminal and type the following:
vue create vueaxiosauth
After installation, move into the folder using the cd vueaxiosauth
.
Installing required packages
Vuex – Vuex is a central store for Vue.js applications. Data stored in the Vuex store can be accessed from any component in the application. To use Vuex in our project, we need to install it in our project. After we have it installed, we can call it from any part of our project.
npm install vuex --save
Vue Router – It is the official routing package for Vue.js. Vue router helps us to navigate the pages of our application. Each page has a specific path or URL or route that we register in our project’s routes.
vue add router
Axios – Axios is an NPM package for making HTTP requests in our node apps.
With Axios, our application can communicate with other web applications. We can send data and retrieve data from other web software through the Rest API.
There are other methods to communicate with web APIs, but we will install and use Axios for their ease and practicality in our project.
npm install axios
Beaufy – Buefy is a lightweight library of responsive UI components for Vue.js based on Bulma framework and design.
npm install buefy
Step 2 – Creating Initial files
Let’s work on the User Interface for our app. Having Vuex & Vue Router directly installed, we need to create two folders called the /views/store
& /views/router
with index.js
file in our project.
We would also need 2 views in our app
- Home.vue
- Mobile.vue
so, Create Home.vue
and Mobile.vue
files in the view folder.
Step 3 – The Code – Vuex and Axios Authentication
Go to the src
folder and open App.vue
delete and add this:
<template>
<div id="app">
<router-view />
</div>
</template>
Now, Open up Home.vue
file and add the following code:
<template>
<section>
<b-notification type="is-info" aria-close-label="Close notification">
Vuex and Axios Authentication example </b-notification>
<b-navbar>
<template #brand>
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<img src="https://codesource.io/ask/assets/logo-4nq0qhfj.png" alt="Codesource Tutorial">
</b-navbar-item>
</template>
<template #start>
<b-navbar-item href="https://codesource.io/">
Visit code-source.tempurl.host
</b-navbar-item>
</template>
</b-navbar>
<b-field label="Username" Username:
:type="{ 'is-danger': hasError }"
:message="{ 'Username is not available': hasError }">
<b-input value="johnsilver" maxlength="30" v-model="username" required> </b-input>
</b-field>
<b-field label="Password" Password:
:type="{ 'is-danger': hasError }"
:message="[
{ 'Password is too short': hasError },
{ 'Password must have at least 8 characters': hasError }
]">
<b-input value="123" type="password" maxlength="30" v-model="password"></b-input>
</b-field>
<b-button label="Login" type="is-primary" @click.prevent="login" />
</section>
</template>
<script>
export default {
name: "home",
data() {
return {
username: "",
password: "",
};
},
methods: {
async login() {
let response = await this.$store.dispatch("login", {
username: this.username,
password: this.password,
});
if (response) {
this.$router.replace("mobiles");
} else {
// you can add condition here
}
},
},
};
</script>
In the code snippet above we Added the data for the login form and a handler for the login button. This will then fire off a dispatch to the store. On a successful login (it will be always successful), $router.replace is used to navigate to the next page. This is done instead of $router.go so that the user cannot hit their back button to return to the login form:
Update Mobile.vue
like below:
<template>
<div>
<b-notification type="is-info" aria-close-label="Close notification">
Vuex and Axios Authentication example
</b-notification>
<b-navbar>
<template #brand>
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<img
src="https://codesource.io/ask/assets/logo-4nq0qhfj.png"
alt="Codesource Tutorial"
/>
</b-navbar-item>
</template>
<template #start>
<b-navbar-item href="https://codesource.io/">
Visit code-source.tempurl.host
</b-navbar-item>
</template>
</b-navbar>
<b-notification
type="is-danger is-light"
aria-close-label="Close notification"
role="alert"
>
<ul>
<li v-for="(mobile, idx) in mobiles" :key="idx">
{{ mobile.name }} brand is {{ mobile.brand }}
</li>
</ul>
</b-notification>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
created() {
this.$store.dispatch("loadMobiles");
},
computed: {
...mapState(["mobiles"])
}
};
</script>
Here, we simply iterate over the mobiles from the store and dispatch a call to the store to load them:
Now, head over to jsonbin.io and create two JSON files to consume the API with the content below.
To load Mobiles List:
[
{
"name": "iphone 12",
"brand": "Apple"
},
{
"name": "S21 ultra",
"brand": "Samsung"
},
{
"name": "MI 10",
"brand": "Xiaomi"
},
{
"name": "oneplus 8",
"brand": "oneplus"
},
{
"name": "iPhone XR",
"brand": "apple"
}
]
Login token:
{
"token": 654373636
}
Below are the APIs for our tutorial.
login - https://api.jsonbin.io/b/600c24d5a3d8a0580c3532b1';
mobile - https://api.jsonbin.io/b/600c2479a3d8a0580c353296';
Now open up store/index.js
file and add the following code:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import axios from 'axios';
const LOGIN_URL = 'https://api.jsonbin.io/b/600c24d5a3d8a0580c3532b1';
const MOBILES_URL = 'https://api.jsonbin.io/b/600c2479a3d8a0580c353296';
export default new Vuex.Store({
state: {
token:'',
mobiles:[]
},
mutations: {
setMobiles(state, mobiles) {
state.mobiles = mobiles;
},
setToken(state, t) {
state.token = t;
}
},
actions: {
loadMobiles(context) {
axios.get(MOBILES_URL,
{
headers: {
'Authorization': 'bearer '+context.state.token
}
})
.then(res => {
context.commit('setMobiles', res.data);
})
.catch(error => {
console.error(error);
});
},
async login(context, credentials) {
return axios.get(LOGIN_URL, {
params:{
username: credentials.username,
password: credentials.password
}
})
.then(res => {
context.commit('setToken', res.data.token);
return true;
})
.catch(error => {
console.error(error);
});
}
}
})
In the code snippet above we are importing Vuex and defining constants for the two endpoints. here we are faking a real API, so the endpoints just return static JSON, the authentication token, and Mobiles. next, we Set up the state and define mutations for them, after that The login action stores the result as a token and the mobiles
action passes the token as an authorization header.
Finally let’s update the Router/index.js
file with the code below:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import store from '../store';
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/mobiles',
name: 'mobiles',
component: () => import(/* webpackChunkName: "mobiles" */ '../views/Mobiles.vue'),
beforeEnter: (to, from, next) => {
if(!store.state.token) {
next('/');
}
next();
}
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
In our application, we don’t want users to access our /mobiles
page Without a token, the call to the endpoint will fail to return valid data.
Lucky for us, Vue Router provides a very simple way to handle this called route guards
. in the code snippet above we are making use of beforeEnter
to handle this call in the mobiles
route.
To be clear Our Main.js
file looks like below:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
Vue.config.productionTip = false
Vue.use(Buefy)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Live demo:
Conclusion
Now we can Handle Vuex and Axios Authentication in Vue by consuming data from an API. Although we are performing fake login here, the logic is the same, but in every API, it’s essential to read the documentation to learn how to fetch data.
I hope you learned a few things about Vue. Every article can be made better, so please leave your suggestions and contributions in the comments below. If you have questions about any of the steps, please do also ask in the comments section below.
You can Checkout Source Code on Github