Verify whether the user is authenticated in a Vue single-page application and redirect them to the login page if not

My VueJS single-page application uses JWT authentication for users.

I am currently working on ensuring that users remain authenticated after a page reload. If the user is not authenticated, they should be redirected to the login page.

The access token and refresh token are stored in both cookies and Vuex:

Vuex.state:

auth: {
        user: {},
        isAuthenticated: false,
        accessToken: null,
        refreshToken: null
    }

Vuex.actions.refreshToken

refreshToken: async ({state, commit, dispatch}) => {
        try {
            await api.jwtRefresh(state.auth.refreshToken).then(response => {
                if (response.status === 200) {
                    dispatch("setAuthData",{
                        accessToken:response.data.access,
                        isAuthenticated:true
                    })
                }
            }).catch(err => {
                dispatch('logout')
            });
        } catch (e) {
            dispatch('logout')
        }
}

In App.vue:

export default {
  data: () => ({}),
  mounted() {
    this.$store.dispatch('setAuthDataFromCookies')
    this.$store.dispatch('refreshToken') // checks if user is authenticated, redirect to login page if not
    this.$router.push('/dashboard')
  }
}

To tackle the issue of immediate redirection before the token is refreshed, I aim to confirm the token validity first. Upon successful refreshing of the JWT token, the user can proceed to /dashboard. In case of failure, the user will be redirected to /login.

The challenge arises from the fact that the mounted method doesn't wait for the refreshToken action to finish its execution before redirecting the user to /dashboard.

How can I resolve this so that the refreshToken action completes before any redirection? My intention is for the refreshToken action to redirect the user to /login upon encountering an error.

Answer №1

To enhance security on your router, consider setting up a meta auth field along with a global guard such as beforeEnter or beforeEach to verify authentication tokens stored in Vuex or cookies.

In the router.js file, include something like this:

routes: [
  {
    name: 'Login'
  },
  {
    name: 'Dashboard', // + path, component, etc
    meta: {
      auth: true
    }
  }
]

You can then implement a global guard as shown below:

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.auth)) {
    if (!store.getters.authToken) {
      next({ name: 'Login' });
    } else {
      next();
    }
  } else {
    next(); // Remember to call next() here!
  }
})

This guard will check the authorization status before each route transition and redirect accordingly based on the presence of the auth meta field.

For more information, refer to the Vue Router Docs on Navigation Guards.

If you are focusing on user authentication, you can integrate endpoint calls within the beforeEach guard and handle redirection based on the response. Ensure that the callback is asynchronous, like so:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtaining a group object when the property value matches the itemSearch criteria

What is the best way to extract specific objects from a group when one of their properties has an array value, specifically using _.lodash/underscore? { "tileRecords" : [ { "tileName" : "Fama Brown", "tileGroup" : ["Polished", "Matt", ...

Step-by-step guide for launching a Next.js/Node application

Currently, I am developing a full-stack project utilizing a next.js application for the front-end and a node/express server for the API. The front-end and back-end are running on separate ports. Here is how my application is configured: https://i.stack.im ...

Is there a way to retrieve arrays nested within an object in Vue or JavaScript?

In my Vue instance, I have a data object named items <script> export default { data() { return { selected: "", items: { item1: [{ selected: "", inputType: "", inputTarget: "" }], ...

Issue encountered when attempting to invoke a PHP function using Javascript through AJAX

I'm currently working on incorporating a PHP function into my HTML file using Ajax (which also contains JavaScript). My goal is to retrieve all locally stored JSON files. I've been following a guide at , but I'm facing some challenges. When ...

Retrieve an array of objects by matching a specific object id

Seeking assistance for a React project centered around a quiz application. Within my database (currently utilizing Firebase Realtime Database), I have a collection of questions and another collection of answers. Questions are identified by an Id, title, an ...

Tips for maximizing the efficiency of a callback when utilizing the filter function in Primefaces for 'myDataTable'

Currently using Primefaces 5.1, and I've encountered a situation where I want to hide a table until after the filter is applied in Javascript. My initial thought was to simply set the css of the table to visibility:hidden;, followed by running the fol ...

Unleashing the power of Sinon: a guide to covertly observing the e

I need to verify if the method "res.render" is invoked with the correct parameters. it("Checks if the page for creating a new user is rendered", done => { const spy = sinon.spy(ejs, "render"); chai .request(app) .get("/users/create ...

The beta version of Angular 2.0 introduces the BrowserDomAdapter for easy access to the DOM

I have a Component in Angular 2.0 that is attempting to utilize the DOM Adapter API from Angular's BrowserDomAdapter documentation. The initialization of this DomAdapter can be found here. However, I am uncertain about whether the Dom Adapter needs t ...

The function of AJAX is to send and receive data asynchronously without

Recently, I was experimenting with AJAX. When I use echo "hello" in my PHP file, everything works perfectly. However, if I try something like echo "<script language=Javascript> alert('hi');</script>"; in the PHP file, the alert ...

The Bootstrap navigation bar is not functioning as expected

After building a landing page with a bootstrap navbar, I noticed that the hamburger menu doesn't display the list of items when the screen size is decreased. Here is the code I used: <nav class="navbar navbar-expand-lg" id="navbar&qu ...

performing an AJAX call utilizing both a file and post data

I'm reaching out for help because I'm having trouble sending an ajax request with a data file and two posts included Here is the code snippet: $('#image--1').change(function (e) { e.preventDefault(); var img = new FormData(); ...

What is the best way to ensure that all input is consistently capitalized in vue.js?

As I work on a form with vue.js, I face the need to have inputs in vue that are always capitalized. My initial thought was to use the CSS property text-transform: uppercase; and then transform the data before sending it using data.someData.toUpperCase() ...

Naming a JSON object twice

As a newcomer to node.js, I find myself struggling with understanding the process. Can someone please guide me on where I might be going wrong? This is how I create a new Product exports.postAddProduct = (req, res, next) => { const product = new Produ ...

How to organize items in an array based on paired values using Angular or Javascript?

In my current scenario, I am working with a substantial array containing 120 objects. Each object within the array possesses an id value and an opposite_id value, essentially forming pairs. I'm looking for the most efficient approach to iterate throug ...

Creating a radio button along with a submit button that redirects to a different local HTML file

Can someone please help with this code? I'm trying to redirect to the value of each radio button when it's clicked. Any guidance or JavaScript code would be greatly appreciated. Thank you. I've tried multiple solutions but none of them seem ...

Converting a string to an array in React when updating the state

Currently, I am working on a React CRUD app that allows me to manage dishes. I can add new dishes, display a list of existing ones, update the details of a dish, or delete a dish. My main challenge at the moment is updating the ingredients of a dish. Whil ...

How can JSON attribute/value pairs be rearranged using JavaScript?

Looking at the JSON data below: [ { 'Album': 'Dearest', 'Artist': 'Theresa Fu', 'Year': '2009'}, { 'Album': 'To be Free', 'Artist': 'Arashi', &apo ...

To use the ModuleWithProviders<T> in the angular-autofocus-fix package, you must provide 1 type argument

Upon successful installation of angular-autofocus-fix I have imported the AutofocusModule However, upon running the Angular project, I encountered the following error: ERROR in node_modules/angular-autofocus-fix/index.d.ts:4:23 - error TS2314: Generic ty ...

Importing TypeScript enums into a Vue or browser context can lead to errors or the need for additional dependencies

I'm encountering a problem when trying to import type definitions from a separate module in my Vue project. Below is the structure of the typedefs I am attempting to import: import { Server, createServer } from "net"; export namespace Testable { ...

Set up a Pinia store with a specific data type

Note: I am a beginner in JavaScript I am currently working on synchronizing an object with a Pinia store and a Python REST API. My goal is to define a type just once without having to duplicate it in the store. export const useTicketStore = defineStore(&a ...