Published: June 07 2022

Vue 3 - Redirect to Login Page if Unauthenticated

Tutorial built with Vue 3.2.33 and Vue Router 4.0.15

This is a quick post to show how to redirect users to the login page in a Vue 3 app that uses Vue Router. The redirect applies to users that attempt to access a secure/restricted page when they are not logged in.

The below code files are part of a Vue 3 JWT authentication tutorial I posted recently that includes a live demo, so to see the code running check out Vue 3 + Pinia - JWT Authentication Tutorial & Example.


Vue 3 Router

Path: /src/helpers/router.js

The router defines the routes for the Vue 3 application and creates a new Vue Router instance with the createRouter() function. The exported router instance is imported into main.js where it is passed to the Vue app on startup.

The createRouter() function is part of Vue Router v4 which is compatible with Vue 3, the previous version of the router (Vue Router v3) is compatible with Vue 2. For more info on what's changed in the new version of the Vue Router see

The home route maps the root path ('/') of the app to the HomeView component and the '/login' route maps to the LoginView component.

Redirect to login from router beforeEach()

Unauthenticated users are prevented from accessing restricted pages by the function passed to router.beforeEach(). If the user is not logged in and trying to access a secure page, the function returns the string '/login' to redirect them to the login page. The requested path (to.fullPath) is assigned to the Pinia auth store property auth.returnUrl so the login page can redirect the user back their desired page after successful login.

For more information on Vue routing see

import { createRouter, createWebHistory } from 'vue-router';

import { useAuthStore } from '@/stores';
import { HomeView, LoginView } from '@/views';

export const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    linkActiveClass: 'active',
    routes: [
        { path: '/', component: HomeView },
        { path: '/login', component: LoginView }

router.beforeEach(async (to) => {
    // redirect to login page if not logged in and trying to access a restricted page
    const publicPages = ['/login'];
    const authRequired = !publicPages.includes(to.path);
    const auth = useAuthStore();

    if (authRequired && !auth.user) {
        auth.returnUrl = to.fullPath;
        return '/login';

Vue 3 Main.js

Path: /src/main.js

The main.js file bootstraps the Vue application by mounting the App component in the #app div element defined in the main index.html file.

Vue routes are configured with the call to app.use(router), routes are defined in router.js.

Pinia support is added to the Vue app with the line app.use(createPinia()).

import { createApp } from 'vue';
import { createPinia } from 'pinia';

import App from './App.vue';
import { router } from './helpers';

// setup fake backend
import { fakeBackend } from './helpers';

const app = createApp(App);



Vue 3 App Component

Path: /src/App.vue

The App component is the root component of the example Vue 3 + Pinia app, it contains the main nav bar which is only displayed for authenticated users, and a RouterView component for displaying the contents of each view based on the current route / path.

The user state property of the Pinia auth store is used to reactively show/hide the main nav bar when the user logs in/out of the application.

The authStore.logout() method is called from the logout link in the main nav bar to log the user out and redirect to the login page.

<script setup>
import { RouterLink, RouterView } from 'vue-router';

import { useAuthStore } from '@/stores';

const authStore = useAuthStore();

    <div class="app-container bg-light">
        <nav v-show="authStore.user" class="navbar navbar-expand navbar-dark bg-dark">
            <div class="navbar-nav">
                <RouterLink to="/" class="nav-item nav-link">Home</RouterLink>
                <a @click="authStore.logout()" class="nav-item nav-link">Logout</a>
        <div class="container pt-4 pb-4">
            <RouterView />

@import '@/assets/base.css';


Need Some Vue 3 Help?

Search fiverr for freelance Vue 3 developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by