Protecting Route for Authenticated Users in Vue.js

The navigation guards provided by vue-router. We are going to use the navigation guards to protect the route. There are a number of ways to implement the navigation guards i.e. global guards, per-route guards and component guards. We are going to implement global guards.

Global Guards

  • beforeEach: action before entering any route
  • beforeResolve: action before the navigation is confirmed but after in-component guards
  • afterEach: action after the route resolves

Per Route Guards

  • beforeEnter: action before entering a specific route

Component Guards

  • beforeRouteEnter: action before navigation is confirmed and before component creation
  • beforeRouteUpdate: action after a new route has been called that uses the same component
  • beforeRouteLeave: action before leaving a route

In my case, We have a membership area that accessible for the authenticated members only. Authentication could be through google, facebook, twitter or email and password. Here we will not focus on the authentication part but only with the client-side authentication area.

Take a look at the navigation menu at the above image. The Member Area is the route that we are going to protect for the authenticated users. Let’s open the index.js file from /src/router directory.

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
import Login from '@/views/Login.vue'
import Signup from '@/views/Signup.vue'
import Members from '@/views/Members.vue'

Vue.use(VueRouter)

    const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/login',
        name: 'Login',
        component: Login
    },
    {
        path: '/signup',
        name: 'Signup',
        component: Signup
    },
    {
        path: '/member-area',
        name: 'Members',
        component: Members
    }
]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

Global Before Guard

Let’s first register a global before guards by using the router.beforeEach. The global before guard is called whenever navigation is triggered. This guard receives three arguments i.e. to, from and next. The next function must be called to resolve the hook.

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

router.beforeEach((to, from, next) => {
});

export default router

The above code does not render any view component because we must call the next() function to resolve the hook.

router.beforeEach((to, from, next) => {
    next();
});

Now, how do we identify which route we have to protected or not? Let’s move to the defined routes again and make the members-area route to protected so that only authenticated users can access it.

Vue.use(VueRouter)

    const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/login',
        name: 'Login',
        component: Login
    },
    {
        path: '/signup',
        name: 'Signup',
        component: Signup
    },
    {
        path: '/member-area',
        name: 'Members',
        component: Members,
        meta: {
            requiresAuth: true
        }
    }
]

We can include a meta field when defining routes. And we have added requiresAuth as a key with a boolean value. It means we require the authentication to access this route but this is not enough. Only defining is not enough to protect this route. We have to check it in the global before guard.

Let’s take an authenticatedUser variable with a null value. This variable will be used to get the authenticated user data from the REST API’s. We are not going to implement any REST API here, that’s why we have defined a value null.

router.beforeEach((to, from, next) => {
    const authenticatedUser = null;
    const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

    // Check for protected route
    if (requiresAuth && ! authenticatedUser) next('login')
    else next();
});

As you see that we have accessed the route meta field through the to argument.

const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

We can identify the protected route through the meta field and add an additional check if we have the authenticated user data or not. And if the protected route is defined and the authenticated user not found then the user must redirect to the login route.

// Check for protected route
if (requiresAuth && ! authenticatedUser) next('login')
else next();

Please find the complete code from here.

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home.vue'
import Login from '@/views/Login.vue'
import Signup from '@/views/Signup.vue'
import Members from '@/views/Members.vue'

Vue.use(VueRouter)

    const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/login',
        name: 'Login',
        component: Login
    },
    {
        path: '/signup',
        name: 'Signup',
        component: Signup
    },
    {
        path: '/member-area',
        name: 'Members',
        component: Members,
        meta: {
            requiresAuth: true
        }
    }
]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

router.beforeEach((to, from, next) => {
    const authenticatedUser = null;
    const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

    if (requiresAuth && ! authenticatedUser) next('login')
    else next();
});

export default router