Every web application that handles user-specific data needs to implement authentication. Knowing how to do this is important for Vue developers, and that’s what this article aims to shed the spotlight on. This tutorial will prove to be useful for beginner developers who want to learn about authentication in Vue. In order to be able to follow along, you’ll need to have a good knowledge of Vue and Vuex.

Authentication is a very necessary feature for applications that store user data. It’s a process of verifying the identity of users, ensuring that unauthorized users cannot access private data — data belonging to other users. This leads to having restricted routes that can only be accessed by authenticated users. These authenticated users are verified by using their login details (i.e. username/email and password) and assigning them with a token to be used in order to access an application’s protected resources.

In this article, you’re going to be learning about:

  1. Vuex Configuration with Axios
  2. Defining Routes
  3. Handling Users
  4. Handling Expired Token
Dependencies

We will be working with the following dependencies that help in authentication:

  • Axios
  • For sending and retrieving data from our API
  • Vuex
  • For storing data gotten from our API
  • Vue-Router
  • For navigation and protection of Routes

We will be working with these tools and see how they can work together to provide robust authentication functionality for our app.

The Backend API

We will be building a simple blog site, which will make use of this API. You can check out the docs to see the endpoints and how requests should be sent.

From the docs, you’ll notice few endpoints are attached with a lock. This is a way to show that only authorized users can send requests to those endpoints. The unrestricted endpoints are the /register and /login endpoints. An error with the status code 401 should be returned when an unauthenticated user attempts to access a restricted endpoint.

After successfully logging in a user, the access token alongside some data will be received in the Vue app, which will be used in setting the cookie and attached in the request header to be used for future requests. The backend will check the request header each time a request is made to a restricted endpoint. Don’t be tempted to store the access token in the local storage.

(Large preview)

Scaffold Project

Using the Vue CLI, run the command below to generate the application:

vue create auth-project

Navigate into your new folder:

cd auth-project

Add the vue-router and install more dependencies — vuex and axios:

vue add router
    npm install vuex axios

Now run your project and you should see what I have below on your browser:

npm run serve

1. Vuex Configuration with Axios

Axios is a JavaScript library that is used to send requests from the browser to APIs. According to the Vuex documentation;

“Vuex is a state management pattern + library 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.”

What does that mean? Vuex is a store used in a Vue application that allows us to save data that will be available to every component and provide ways to change such data. We’ll use Axios in Vuex to send our requests and make changes to our state (data). Axios will be used in Vuex actions to send GET and POST, response gotten will be used in sending information to the mutations and which updates our store data.

To deal with Vuex resetting after refreshing we will be working with vuex-persistedstate, a library that saves our Vuex data between page reloads.

npm install --save vuex-persistedstate

Now let’s create a new folder store in src, for configuring the Vuex store. In the store folder, create a new folder; modules and a file index.js. It’s important to note that you only need to do this if the folder does not get created for you automatically.

import Vuex from 'vuex';
import Vue from 'vue';
import createPersistedState from "vuex-persistedstate";
import auth from './modules/auth';

// Load Vuex
Vue.use(Vuex);
// Create store
export default new Vuex.Store({
  modules: {
    auth
  },
  plugins: [createPersistedState()]
});

Here we are making use of Vuex and importing an auth module from the modules folder into our store.

Modules

Modules are different segments of our store that handles similar tasks together, including:

  • state
  • actions
  • mutations
  • getters

Before we proceed, let’s edit our main.js file.

import Vue from 'vue'
import App from './App.vue'
import router from './router';
import store from './store';
import axios from 'axios';

axios.defaults.withCredentials = true
axios.defaults.baseURL = 'https://gabbyblog.herokuapp.com/';

Vue.config.productionTip = false
new Vue({
  store,
  router,
  render: h => h(App)
}).$mount('#app')

We imported the store object from the ./store folder as well as the Axios package.

As mentioned earlier, the access token cookie and other necessary data got from the API need to be set in the request headers for future requests. Since we’ll be making use of Axios when making requests we need to configure Axios to make use of this. In the snippet above, we do that using axios.defaults.withCredentials = true, this is needed because by default cookies are not passed by Axios.

aaxios.defaults.withCredentials = true is an instruction to Axios to send all requests with credentials such as; authorization headers, TLS client certificates, or cookies (as in our case).

We set our axios.defaults.baseURL for our Axios request to our API This way, whenever we’re sending via Axios, it makes use of this base URL. With that, we can add just our endpoints like /register and /login to our actions without stating the full URL each time.

Now inside the modules folder in store create a file called auth.js

//store/modules/auth.js

import axios from 'axios';
const state = {

};
const getters = {

};
const actions = {

};
const mutations = {

};
export default {
  state,
  getters,
  actions,
  mutations
};
state

In our state dict, we are going to define our data, and their default values:

const state = {
  user: null,
  posts: null,
};

We are setting the default value of state, which is an object that contains user and posts with their initial values as null.

Actions

Actions are functions that are used to commit a mutation to change the state or can be used to dispatch i.e calls another action. It can be called in different components or views and then commits mutations of our state;

Register Action

Our Register action takes in form data, sends the data to our /register endpoint, and assigns the response to a variable response. Next, we will be dispatching our form username and password to our login action. This way, we log in the user after they sign up, so they are redirected to the /posts page.

async Register({dispatch}, form) {
  await axios.post('register', form)
  let UserForm = new FormData()
  UserForm.append('username', form.username)
  UserForm.append('password', form.password)
  await dispatch('LogIn', UserForm)
},

Login Action

Here is where the main authentication happens. When a user fills in their username and password, it is passed to a User which is a FormData object, the LogIn function takes the User object and makes a POST request to the /login endpoint to log in the user.

The Login function finally commits the username to the setUser mutation.

async LogIn({commit}, User) {
  await axios.post('login', User)
  await commit('setUser', User.get('username'))
},

Create Post Action

Our CreatePost action is a function, that takes in the post and sends it to our /post endpoint, and then dispatches the GetPosts action. This enables the user to see their posts after creation.

async CreatePost({dispatch}, post) {
  await axios.post('post', post)
  await dispatch('GetPosts')
},

Get Posts Action

Our GetPosts action sends a GET request to our /posts endpoint to fetch the posts in our API and commits setPosts mutation.

async GetPosts({ commit }){
  let response = await axios.get('posts')
  commit('setPosts', response.data)
},

Log Out Action

async LogOut({commit}){
  let user = null
  commit('logout', user)
}

Our LogOut action removes our user from the browser cache. It does this by committing a logout:

Mutations
const mutations = {
    setUser(state, username){
        state.user = username
    },
    setPosts(state, posts){
        state.posts = posts
    },
    LogOut(state){
        state.user = null
        state.posts = null
    },
};

Each mutation takes in the state and a value from the action committing it, aside Logout. The value gotten is used to change certain parts or all or like in LogOut set all variables back to null.

Getters

Getters are functionalities to get the state. It can be used in multiple components to get the current state. The isAuthenticatated function checks if the state.user is defined or null and returns true or false respectively. StatePosts and StateUser return state.posts and state.user respectively value.

const getters = {
    isAuthenticated: state => !!state.user,    
    StatePosts: state => state.posts,
    StateUser: state => state.user,
};

Now your whole auth.js file should resemble my code on GitHub.

#vue #javascript #web-development #programming #developer

Authentication In Vue.js
2.70 GEEK