Firebase Auth and Vue-router

非 Y 不嫁゛ 提交于 2019-12-04 02:12:01

Firebase always triggers an auth state change event on startup but it's not immediate.

You'll need to make authService.authenticated return a promise in order to wait for Firebase to complete its user/auth initialisation.

const initializeAuth = new Promise(resolve => {
  // this adds a hook for the initial auth-change event
  firebase.auth().onAuthStateChanged(user => {
    authService.setUser(user)
    resolve(user)
  })
})

const authService = {

  user: null,

  authenticated () {
    return initializeAuth.then(user => {
      return user && !user.isAnonymous
    })
  },

  setUser (user) {
    this.user = user
  },

  login (email, password) {
    return firebase.auth().signInWithEmailAndPassword(email, password)
  },

  logout () {
    firebase.auth().signOut().then(() => {
      console.log('logout done')
    })
  }
}

You don't need to call setUser from the signInWith... promise as this will already be handled by the initializeAuth promise.

I just had this same problem and ended up delaying the creation of the Vue object until the first onAuthStatedChanged.

# main.js
// wait for first firebase auth change before setting up vue
import { AUTH_SUCCESS, AUTH_LOGOUT } from "@/store/actions/auth";
import { utils } from "@/store/modules/auth";
let app;
firebase.auth().onAuthStateChanged(async user => {
  if (!app) {
    if (user) {
      await store.dispatch(AUTH_SUCCESS, utils.mapUser(user));
    } else {
      await store.dispatch(AUTH_LOGOUT);
    }
    app = new Vue({
      router,
      store,
      i18n,
      render: h => h(App)
    }).$mount("#app");
  }
});

And then in my route I check as normal and if they end up on login route I just push them to my overview page which is kind of my dashboard page.

#router.js
router.beforeEach((to, from, next) => {
  let authenticated = store.getters.isAuthenticated;
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!authenticated) {
      next({
        name: "Login",
        query: { redirect: to.fullPath }
      });
    } else {
      next();
    }
  } else {
    // doesn't require auth, but if authenticated already and hitting login then go to overview
    if (authenticated && to.name === "Login") {
      next({
        name: "Overview"
      });
    }
    next(); // make sure to always call next()!
  }
});

To build on Richard's answer, for those who are using regular Vue (not Vuex)

main.js

//initialize firebase
firebase.initializeApp(config);
let app: any;
firebase.auth().onAuthStateChanged(async user => {
if (!app) {
    //wait to get user
    var user = await firebase.auth().currentUser;

    //start app
    app = new Vue({
      router,
      created() {
        //redirect if user not logged in
        if (!user) {
          this.$router.push("/login");
        }
      },
      render: h => h(App)
    }).$mount("#app");
  }
});

router.js

//route definitions
//...
router.beforeEach((to, from, next) => {
  const currentUser = firebase.auth().currentUser;
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

  if (requiresAuth && !currentUser) {
    const loginpath = window.location.pathname;   
    next({ name: 'login', query: { from: loginpath } });
  } else if (!requiresAuth && currentUser) {
    next("defaultView");
  } else {
    next();
  }
});

You have two options:

1) Use beforeRouteEnter from the component:

export default {
        name: "example",
        ....
        beforeRouteEnter(to, from, next){
            if (authService.authenticated()) {
                next()
            } else {
                next('/login')
            }
        },
}

2) use beforeResolve from the router.

router.beforeResolve((to, from, next) => {

    if(to.fullPath === '/example' && !authService.authenticated()){
        next('/login')
    }else{
        next()
    }
})

Life-circle of Vue route guards

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!