Have you ever encountered the frustration of being unable to navigate to the next page even after successfully logging in due to issues

I'm currently utilizing Vue and Firebase to build my application. One of the features I want to implement is the redirect method using vue-router.

Within my vue-router code, I've included meta: { requiresAuth: true } in multiple pages as middleware.

The redirect logic in my vue-router is designed to send users to /login if the JWT token is not stored in local storage upon login.

Given that I'm leveraging Firebase for user authentication, I expect the user account token to be stored in local storage once a user logs in successfully. Assuming my Vuex code is correct, the vue-router should function as intended.

Upon logging in as a user, the URL remains unchanged. However, when navigating to a specific user's dashboard page, the redirect functionality works smoothly.

I am puzzled by the fact that the URL does not change after logging in. Why might this be happening?

import Vue from 'vue'
import VueRouter from 'vue-router'
//import Home from '../views/Home.vue'
import Dashboard from '../views/Dashboard.vue'
import OrdersMobile from '../views/OrdersMobile.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "about" */ '../selfonboarding/Home.vue')
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import(/* webpackChunkName: "about" */ '../components/Login.vue')
  },
  {
    path: '/dashboard/',
    name: 'Dashboard',
    component: Dashboard,
    meta: { requiresAuth: true },
    children: [
      {
        path: 'products/:id',
        name: 'Products',
        component: () => import(/* webpackChunkName: "about" */ '../views/Products.vue')
      },
      {
        path: 'working-hours/:id',
        name: 'WorkingHours',
        component: () => import(/* webpackChunkName: "about" */ '../views/WorkingHours.vue')
      },
      // {
      //   path: 'pictures/:id',
      //   name: 'Pictures',
      //   component: Pictures,
      // },
      {
        path: 'orders/:id',
        name: 'Orders',
        component: () => import(/* webpackChunkName: "about" */ '../views/Orders.vue')
      },
      {
        path: 'orders.s/:id',
        name: 'OrdersMobile',
        component: OrdersMobile,
        children: [
          {
            path: 'processed',
            name: 'Processed',
            component: () => import(/* webpackChunkName: "about" */ '../views/Processed.vue')
          }
        ]
      },
      {
        path: 'information/:id',
        name: 'Information',
        component: () => import(/* webpackChunkName: "about" */ '../views/Information.vue')
      },
      {
        path: 'information.s/:id',
        name: 'InformationMobile',
        component: () => import(/* webpackChunkName: "about" */ '../views/InformationMobile.vue')
      },
    ]
  }
]


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


router.beforeEach((to, from, next) => {
  if(to.matched.some(record => record.meta.requiresAuth)) {
      if (localStorage.getItem('jwt') == null) {
          next({
              path: '/login',
              params: { nextUrl: to.fullPath }
          })
      } 
  } else {
      next()
  }
})


export default router

Vuex Code at ../store/user.js

import 'firebase/firebase-auth'
import fireApp from '@/plugins/firebase'
import router from '../../router'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();

const state = {
    currentUser: null
}

const getters = {
    currentUser: state => state.currentUser
}

const mutations = {
    userStatus: (state, user) => {
       
        user === null ? state.currentUser = null : state.currentUser = user.email
      }
}

const actions = {
 signIn: async ({ commit }, user) => {
    try {
      const userData = await fireApp.auth().signInWithEmailAndPassword(
          user.email,
          user.password
      );

        // Get the user id (from the user object I guess)
        const userId = fireApp.auth().currentUser.uid;
        // or maybe through  const userId = fireApp.auth().currentUser.uid;

        const proUserDocRef = db.collection('ProUser').doc(userId);
                    
        proUserDocRef.get().then((doc) => {
                if(doc.exists && doc.data().status === true) {
                    router.push({name:'Products',params:{id: userId}}).catch(err => {})
                } else if(doc.exists && doc.data().status === false){
                    router.push({name:'Welcome',params:{id: userId}}).catch(err => {})
                } else {
                    alert('You are not registered as a pro user.')
                }
        })

        
    }
    catch(error) {
        const errorCode = error.code
        const errorMesage = error.message
        if(errorCode === 'auth/wrong-password') {
            alert('wrong password')
        } else {
            alert(errorMesage)
            }
        }
    },

    signOut: async({ commit }) => {
        try {
            await fireApp.auth().signOut()
        }
        catch(error) {
            alert(`error sign out, ${error}`)
        }
        commit('userStatus', null)
    }
}

export default {
    state,
    mutations,
    getters,
    actions
}

Answer №1

The beforeEach navigation guard is missing a critical step when handling authentication and logged-in users:

router.beforeEach((to, from, next) => {
  if(to.matched.some(record => record.meta.requiresAuth)) {
      if (localStorage.getItem('jwt') == null) {
          next({
              path: '/login',
              params: { nextUrl: to.fullPath }
          })
      } else {
          next();     // Don't forget this important call ✅
      }
  } else {
      next()
  }
})

Answer №2

After some troubleshooting, I managed to successfully implement the following code snippet into the user.js actions section:

const token = await firebase.auth().currentUser.getIdToken(true)
localStorage.setItem('jwt', token)

As a result, I was able to address the issue I was facing.

Initially, I struggled with setting the jwt token in the local storage, but eventually solved it by incorporating this step when logging into the website.

I also realized that I had forgotten to include 'next()' in my code.

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

React Application Issue: Unable to successfully redirect to the homepage upon logging in

Attempting to create a web application with the MERN stack is causing some trouble when trying to redirect users to the home page post-login. Here's how it should ideally function: User inputs login details The server validates these details and gene ...

The Action Creator is not being waited for

In my application, I am using a placeholder JSON API to fetch posts and their corresponding users. However, I encountered an issue where the user IDs were being duplicated and fetched multiple times. To resolve this, I implemented the following code snippe ...

How can I showcase a Google donut chart using an array of data in a React application?

I have created a doughnut chart that is supposed to take an array as data. However, when I input the array, nothing shows up on the chart. How can I create a chart with array data? sum.js ... const arr = []; arr.push({ key: capitalizeEachFirst ...

Data extracted from the range selector

Is there a way to take values and use them for hiding or displaying certain divs? I have been using jQuery Simple Slider for this purpose. I attempted the following code, but it did not work well. I want the div with id "3" to be visible when the slider ...

Array of materials for ThreeJS GLTFLoader

Attempting to load a model using GLTFLoader and apply different colors for each face of the object (cube) using a material array is not functioning as expected. var materials = [ new THREE.MeshPhongMaterial( {color: 0x552811,specular: 0x222222,shininess: ...

Create a function that generates an HTML string and returns it to be used in JSX

As a newcomer to JSX/React, I am seeking guidance on removing inline code. I have created a function that returns the value to be displayed in the template/JSX. The function works well except when it needs to return a string along with an element like a Li ...

How do I delete an attached file in an input document? (Firefox)

Is there a way to smoothly remove an attachment selected in the <input type="file"> element? In Firefox, removing an already selected attachment can be tricky. Simply deleting the name or trying to click open may not work. An additional solution mi ...

Difficulty occurred when trying to import Polymer components

Currently, I am in the process of learning how to utilize Polymer. I meticulously followed the instructions provided exactly as specified here. However, upon reaching step 3 and adding the import for paper-checkbox, an error presented itself: Error: A c ...

JavaScript drag functionality is jerky on iPads, not seamless

I am currently attempting to implement a feature where I can drag a div (#drag) within its parent container (#container) using only pure JavaScript. This functionality is specifically required to work on iPad devices only. After writing a script that func ...

Unable to find 'three' within the three-gltf-loader

I'm facing a new challenge and seeking help here as I couldn't find a solution on my own. I am currently working on a project that combines three.js with Vue.js. The specific error message I received is: Failed to compile. ./node_modules/three- ...

Harnessing the Power of Google Tag Script in Next.js

After researching How to load Google Tag Manager with the next/script component (Next.js 11) and reviewing this documentation page, my issue remains unresolved. I am looking to implement Google Tag on multiple websites developed using nextjs, so I created ...

Passing string values to an onClick event listener in Javascript is similar to how it is done in an onclick event listener in HTML

render() { return ( <div> <div onClick={() => "FSR.launchFeedback('ax9sgJjdSncZWoES6pew6wMIyCgSXpC')" } /> </div> ); } This piece of code initially appear ...

Using the "i" parameter in a Lodash for loop results in undefined, however, it functions properly with specific values set

My goal is to use Lodash to search for specific integer values in an object and then store some of those values in an array. The integers are variable and come from a separate array, but I am consistently getting undefined as the result. If I manually inp ...

Using VueJS Single File Components can cause issues with the example code for "Custom Popups" in the Google Maps API

Trying to implement a unique Google Maps popup following the provided documentation. After copying and pasting the official Google example code into a VueJS jsFiddle, the custom marker functions correctly as intended. It remains in the designated area eve ...

Despite having unique ids, two file input forms are displayed in the same div in the image preview

Running into a minor issue once again. It may not be the most eloquent query, but I'm genuinely stuck and in need of some assistance. I am attempting to showcase image previews of selected files in a file input form. I have a jQuery script that reads ...

How can we handle multiple asynchronous calls within a function?

In the process of developing a dynamic page with heavy AJAX interactions that update values in selectors based on prior selections. Currently, working on implementing a "repopulate" feature to fill in selectors based on previous entries. Whenever Selector ...

Display solely the initial row in the tbody segment of a table. Is there a method to obscure subsequent 1st rows?

The initial row of each tbody acts as the row header, containing the column names. Subsequent rows in each tbody are unnecessary and should be hidden. Classes utilized: toprowHeader = first row containing column names recordsRow = holds additional recor ...

There was a failure to establish a Redis connection to the server with the address 127.0.0.1 on port 6379

Currently, I am working with node.js using expressjs. My goal is to store an account in the session. To test this out, I decided to experiment with sessions by following the code provided on expressjs var RedisStore = require('connect-redis')(ex ...

Experience the click action that comes equipped with two unique functions: the ability to effortlessly add or remove a class

Currently, I am in the process of creating a list of anchor links that contain nested anchor links, and there are a few functionalities that I am looking to implement. Upon clicking on a link: Add a class of "current" Remove the class of "current" from ...

Finding the current week using date information from an array of objects in JavaScript

I have an array of objects with a date key, and I am trying to filter out the objects that fall within the current week. How can I achieve this and get the objects from the current week? I attempted to use the filter method, but I believe I need to forma ...