No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Firebase onAuthStateChanged and beforeEach (Navigation Guard)

    Help
    4
    7
    2332
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • V
      venkyvb last edited by

      I am seeing an issue in my Quasar app with regards to browser refresh and firebase authentication.

      When a user logs in and then clicks on the browser refresh, then the firebase.auth().currentUser returns null (as this executes asynchronously). This means that when the beforeEach gets executed the currentUser is null and the user is prompted with the logon page. However I see that when the callback to onAuthStateChanged() is getting invoked the user is getting set correctly.

      Is there any pattern by which, in a Quasar app, the onAuthStateChanged() can be used in navigation process so that existing user session is reused?

      // router/index.js 
      ...
      firebase.auth().onAuthStateChanged(user => {
        console.log('onAuthStateChanged Invoked => ' + user);
      });
      
      router.beforeEach((to, from, next) => {
        let currentUser = firebase.auth().currentUser; 
        let requiresAuth = to.matched.some(record => record.meta.requiresAuth);
      
        if (requiresAuth && !currentUser) {
          next('signin');
        } else {
          if (requiresAuth && currentUser.emailVerified === false) {
            next('signin');
          } else {
            next();
          }
        }
      });
      ...
      

      One pattern that is used in Vue applications is to initialize the app within the onAuthStateChanged callback. From the Quasar docs, I dont see how this can be done.

      1 Reply Last reply Reply Quote 0
      • V
        venkyvb last edited by

        Came across this solution in the Vuejs forum https://forum.vuejs.org/t/vue-routes-firebase-auth-sync-problem/4470

        Solution is to wrap the firebase.auth().currentUser within a Promise and then execute the logic within the beforeEach based on the resolution of the Promise.

        1 Reply Last reply Reply Quote 0
        • J
          Joshua last edited by

          Hi Venkyvb,

          I’m a little late to the party, but I’m having the same issue-- in boot. Its kind of works but I got boot errors and extensions are not working. Would you mind posting a quick excerpt of your completed solution?

          I’m currently mounting handleAuthStateChange in App.vue and triggering it from the store which is causing refresh issues.

          1 Reply Last reply Reply Quote 0
          • tlloyduk
            tlloyduk last edited by

            This would be useful for me too

            1 Reply Last reply Reply Quote 0
            • kms695
              kms695 last edited by

              Hi, I also struggled a lot with this one (with other frameworks also…), but my solution with Quasar seems to work. It is the promised-based approach which I include in the my Router index.js, not in any boot file.

              If changes to the user state are made, I dispatch the new state to vuex only from the Router, because if my user logs in s/he is redirected to a dashboard and if logged out redirected to another page.

              export default function ({ store }) {
                const router = new VueRouter({
                  ...
                })
              
                router.beforeEach(async (to, from, next) => {
                  const user = await new Promise((resolve, reject) => {
                    firebaseAuth.onAuthStateChanged(user => {
                      store.dispatch('myFirebaseUserAction', user.toJSON())
                      resolve(user)
                    })
                  })
              
                  const requiresAuth = to.matched.some(recordedRoute => recordedRoute.meta.requiresAuth)
              
                  if (requiresAuth && !user) {
                    next({ path: 'login', query: { from: to.path } })
                  } else {
                    next()
                  }
                })
                return router
              }
              
              1 Reply Last reply Reply Quote 2
              • tlloyduk
                tlloyduk last edited by

                Yep, I arrived at almost an identical solution too 🆒

                1 Reply Last reply Reply Quote 0
                • kms695
                  kms695 last edited by

                  Would be awesome if you share this directly next time 💪🏻

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post