DEV Community

Cover image for User authentication with Axios, Vue Js and Nuxt Js.
NERØ
NERØ

Posted on

User authentication with Axios, Vue Js and Nuxt Js.

After struggling with user authentication in my nuxt app for quite a while, I was able to find a solution with the help of a friend and I would love to share it with you. Let's go!

Prerequisites

This article asumes that you are familiar with the basics of web development as well as the basics of vuejs. If you are not familiar with vue js check out this turorial.

Project Structure

Project Structure

This is the project structure for our Nuxt Authentication with axios application.

Setup Nuxt Project

I would be using npm so to follow along with this tutorial you will need to install:

npm install axios vuex-persist vuex
Enter fullscreen mode Exit fullscreen mode

vuex-persist
If you are not familiar with vuex-persist, it is a third party library in the vue ecosystem that saves the user's data in the browser's local or session storage (depending on your configuration). This enables the user to close a browser window and return with his details and data intact.

vuex-toasted helps display formatted messages to the user. Could be error messages or success messages.

After installation your package.json should look like this:

Package.json

Ignore the packages not discussed in this tutorial. Focus on the versions of the ones used. Specifically: Axios, vuex-toasted and vuex-persist. If you are using Nuxt you should have axios and vuex pre-installed so that saves you some time.

Backend Api routes

Assuming you have a fully functional backend api with a base url of localhost:3000/backend/api/ you would need 2 routes: the register and login routes. For this tutorial we would be using:

- register route : auth/signup
- login route: auth/signin
Enter fullscreen mode Exit fullscreen mode

vuex store

The vuex store handles the state of our user data. From it we retrieve and store the user login details in the state function.

  • Import your vuex-persist plugin into your vuex store so it has access to your global state variables.
import VuexPersistence from 'vuex-persist'

function getPlugins() {
  const plugins = []

  if (process.browser) {
    const vuexLocal = new VuexPersistence({
      storage: window.localStorage,
    })

    plugins.push(vuexLocal.plugin)
  }
  return plugins
}

export const plugins = getPlugins()

export const state = () => ({
  userDetails: [],
})

export const mutations = {
  setUserDetails(state, val) {
    state.userDetails = val
  },
}

Enter fullscreen mode Exit fullscreen mode

We use the store to hold state data. Which in this case is the user's authentication info which helps us manage the flow of data throughout the application's runtime.

Login page:

Login Page

login.vue

<form @submit="login()" enctype="multipart/form-data" method="post">
          <div class="fields">
            <label for="email"><strong>Email Address</strong></label>
            <input type="email" name="email" v-model="email" />

            <label for="email"><strong>Password</strong></label>
            <input type="password" name="email" v-model="password" />
            <span class="forgot">
              Use Uppercase, Lowercase and Numeric characters*
            </span>
          </div>
          <div>
            <div class="btn">
              <button type="button" @click="login()">
                Sign In
              </button>
            </div>
          </div>
        </form>
Enter fullscreen mode Exit fullscreen mode

Axios requests

You would notice we get the user information from the store by calling this.$store.state.userDetails. This is how user state is accessed from the store.

Next we make a post request to the signin endpoint supplying the API with the user data in the data object. The API then checks if the user exists and returns a response of successful.

We can now proceed to store the userdata in the local storage by committing the user data to the vuex store. The vuex persist plugin we imported in the store would save the data to enable persistent state between user sessions.

<script>
import axios from 'axios'
export default {
  data() {
    return {
      email: '',
      password: '',
      userInfo: this.$store.state.userDetails,
    }
  },
  methods: {
    async login() {
      const data = {
        email: this.email,
        password: this.password,
      }
      axios
        .post('localhost:3000/backend/api/auth/signin', data)
        .then((res) => {
          const userData = res.data
          userData.user.token = userData.token
          this.$store.commit('setUserDetails', userData.user)
          this.$toasted.show('You have logged in successfully', {
            position: 'top-center',
            duration: 500,
            type: 'success',
          })
          this.$router.push('/home')
        })
        .catch((err) => {
          this.$toasted.show(
            'Please enter the correct details and try again',
            err,
            {
              position: 'top-left',
              duration: 200,
              type: danger,
            }
          )
        })
    },
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode

Register Page:

register.vue

register.vue

<form @submit="register()" enctype="multipart/form-data" method="post">
          <div class="names">
            <div class="name">
              <label for="firstname"><strong>First Name</strong></label>
              <input type="text" name="firstname" v-model="firstname" />
            </div>
            <div class="name">
              <label for="lastname"><strong>Last Name</strong></label>
              <input type="text" name="lastname" v-model="lastname" />
            </div>
          </div>
          <div class="fields">
            <label for="email"><strong>Email Address</strong></label>
            <input type="email" name="email" v-model="email" />

            <label for="password"><strong>Password</strong></label>
            <input type="password" name="password" v-model="password" />
            <span class="forgot">
              Use Uppercase, Lowercase and Numeric characters*
            </span>
          </div>

          <div class="btn">
            <button type="button" @click="register()">
              Sign Up
            </button>
          </div>
    </form>
Enter fullscreen mode Exit fullscreen mode

axios requests

<script>
import axios from 'axios'
export default {
  data() {
    return {
      firstname: '',
      lastname: '',
      email: '',
      password: '',
      error: null,
    }
  },

  methods: {
    async register() {
      const data = {
        firstname: this.firstname,
        lastname: this.lastname,
        email: this.email,
        password: this.password,
      }
      axios
        .post('localhost:3000/backend/api/auth/signup', data)
        .then((res) => {
          const userData = res.data
          this.$toasted.show('You have registered successfully', {
            theme: 'primary',
            position: 'top-center',
            duration: 5000,
            type: 'success',
          })
          this.$router.push('/auth/login')
        })
    },
  },
}
</script>

Enter fullscreen mode Exit fullscreen mode

Vuex Toast Notifications:

This is a simple notification system that makes the helps create a good user experience. As seen above, the usage is simple. Specify your message as the first parameter to the toasted.show() method and then the specific configuration for the message type.

Your application would access these plugins (vuex-toasted and vuex-persist) from the files below.

Create a plugins folder and in it create two files like so:

plugins folder

We would use these files to host the configurations for vuex-persist and vuex-toast respectively.

vuex-persist.js

import VuexPersistence from 'vuex-persist'

export default ({ store }) => {
  new VuexPersistence({
    /* your options */
  }).plugin(store)
}

Enter fullscreen mode Exit fullscreen mode

vuex-toasted.js

import Vue from 'vue'

import Toasted from 'vue-toasted'

if (process.browser) {
  Vue.use(Toasted)
}

Enter fullscreen mode Exit fullscreen mode

As explained above, these files are meant to host the configurations for their respective packages.

You should try to make these code examples work with your specific use-case. Once you do that everything should work fine.

I am sure you are happy-crying now as you realize this long-ass article has finally come to an end.

Either way, let me know in the comments what do you think about the code and please do give suggestions for improvements, they will be greatly appreciated!

Oldest comments (2)

Collapse
 
rumbis profile image
George Alexandrou

i didn't found the way to make it work on nuxt 3 !

Collapse
 
reallifenero profile image
NERØ • Edited

Are you getting any error message? Can you send the details of your problem?