skip to Main Content

I am using:

[email protected]
[email protected]
[email protected]

I am working with Firebase and I use a pinia Store for the authentication. The way I am doing it as of now is:

  1. I have a pinia store called storeAuth.ts with following code (part of the code):
...

export const useStoreAuth = defineStore('storeAuth', () => {
  const user = ref(null)
  const loading = ref(false)
  const errorMessage = ref("")
  const successMessage = ref("")
  const router = useRouter()

  const init = () => {
    onAuthStateChanged(auth, (firebaseUser) => {  
      if (firebaseUser) {
        user.value = {}
        user.value.id = firebaseUser.uid
        user.value.email = firebaseUser.email
        console.log('logged in:',user);
      } else {
        user.value = null
        //console.log('logged out');
      }
    });
  }
...
const loginUser = (credentials) => {
    successMessage.value = ""
    errorMessage.value = ""
    loading.value = true

    signInWithEmailAndPassword(auth, credentials.email, credentials.password).then((userCredential) => {
      loading.value = false
      const firebaseUser = userCredential.user;
      router.push('/')
    }).catch((error) => {
      loading.value = false
      //console.log('Error while logging in:',error.message);
      switch (error.code) {
        case 'auth/user-not-found':
          errorMessage.value = "Email and/or password incorrect"
          break;

        case 'auth/wrong-password':
          errorMessage.value = "Email and/or password incorrect"
          break;

        case 'auth/too-many-requests':
          errorMessage.value = "Too many requests. Please reset your password"
          break;

        default:
          errorMessage.value = "There was an error during login"
          break;
      }
    });
  }
...

So I call the function loginUser with my credentials and then I am logged in.

Now I would like to use route guards in order to prevent going to the login page when user is signed in. I tried to do it getting the user from the pinia store as I am storing the value in a user variable in my pinia store in the init function. But it is always null when entering in the router/index.ts . So I have tried the following approach :
I enter this following config in my router file :

let currentUser = null

const getCurrentUser = async () => {
  return new Promise<void>((resolve) => {
    onAuthStateChanged(auth, (user) => {
      currentUser = user
      resolve()
    })
  })
}

const setupNavigationGuards = async () => {
  await getCurrentUser()

  router.beforeEach((to, from, next) => {
    currentUser = auth.currentUser

    if (currentUser && (to.name === 'signin' || to.name === 'register')) {
      next({ name: 'home' })
    } else {
      next()
    }
  })
}

// Call the setupNavigationGuards function
setupNavigationGuards()

But it is not working and on top of that I would prefer to use the user from my pinia and not the user from Firebase because I would like also to add some roles and show menus to the admins only…

2

Answers


  1. Chosen as BEST ANSWER

    I found a way to refactor my init function into a Promise: In my storeAuth, the init function looks like this:

    const init = () => {
          return new Promise((resolve) => {
          onAuthStateChanged(
            auth,
            (firebaseUser) => {
              if (firebaseUser) {
                user.value = {}
                user.value.id = firebaseUser.uid
                user.value.email = firebaseUser.email
                //console.log('logged in:',user.value);
              } else {
                user.value = null
                //console.log('logged out');
              }
              resolve(user.value)
            }
          )
        })
      }
    

    and in my router index file, I call it like this:

    router.beforeEach(async (to) => {
      const storeAuth = useStoreAuth()
      await storeAuth.init()  
      
      if (storeAuth.user && (to.name === 'signin' || to.name === 'register')) {
        return { name: 'home'}
      } else {
        return
      }
    })
    

  2. To get the correct user value from your store you have to call your store’s useStoreAuth function from inside the route guard.

    router.beforeEach((to, from, next) => {
      const store = useStoreAuth()
    
      if (store.user && (to.name === 'signin' || to.name === 'register')) {
        next({ name: 'home' })
      } else {
        next()
      }
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search