Vue 2 SPA restricting components for logged-in users only

Who doesn’t need authentication middleware to secure their app? Not me. In SPAs (Single Page Applications), this could seem tricky according to your development background. Having a Laravel background, it makes more sense to me to apply authentication middleware to routes. Fortunately, VueJS official router facilitates that thanks to its ‘beforeEnter’, to which you may apply guards. This is how I do it.

First, let’s create a middleware service in ‘src/services/middleware.js’. Not that I use vue-cli to generate the project.


import user from './auth'

export default {
    guest (to, from, next) {
        next(!user.check())
    },

    auth (to, from, next) {
        next(user.check() ? true : {
            path: '/login',
            query: {
                redirect: to.name
            }  
        })
    }
}

You can see most of the vocabulary is borrowed from Laravel, though the query looks more like Express. The guest() method only allows guest users for pages like Login and Sign Up. Conversely, the auth() function only allows authenticated users, else redirect to login with the intended route as a URL parameter like http://localhost/login?redirect=dashboard.

Now, let’s define /src/services/auth.js

import Vue from 'vue'

export default {
    user () {
        return this.$store.state.user
    },

    check () {
        return localStorage.getItem('token') //get token from localStorage 
    }
}

At last, in our router, we can check for user authentication on a per route basis.

src/router/index.js


import Vue from 'vue'
import Router from 'vue-router'
import Guard from '../services/middleware'

import NotFoundComponent '@/components/notfound'
import LoginComponent from '@/components/login'
import DashboardComponentfrom '@/components/dashboard'


Vue.use(Router)

export default new Router({
    mode: 'history',
    routes: [
        { path: '/login', name: 'login', component: LoginComponent, beforeEnter: Guard.guest },
        { path: '/dashboard', name: 'dashboard', component: DashboardComponent, beforeEnter: Guard.auth }
        { path: '*', component: NotFoundComponent }
    ]
})

From the above routes, ‘login’ will only be available to guests, whereas ‘dashboard’ will require authentication. Then the ‘catch-all-routes’ will be displayed to both guests and authenticated users if they enter random URLs.

I can’t get over Madrid loosing to Barcelona at home. Such is life.