[Solved] auth check with firebase



  • Hi Guys,

    First of all, im kinda new. People told me to just jump in and pick up a project since that is the best way to learn.

    I have set up an quasar project with a firebase backend (note: I didn’t use a template so I might just have missed something) and everything seems to be working great. I have an observer on the auth state in my default.vue to see if a user is logged in and redirect to the login page when that is not the case like this:

    beforeCreate() {
    this.$auth.onAuthStateChanged((user) => {
    if (!user) {
    console.log(‘user not logged in, sending to loginpage’);
    this.$router.push({ path: ‘login’ });
    }
    });
    },

    Now if one would navigate to mydomain.com/home this would render default.vue and trigger a redirect to /login because the user is not logged in. However (and this is the problem) if you navigate to /home again directly after this you will be able to reach the page without being logged in.

    I assume a best practice would be to add some kind of auth check in the routing, but I am not sure how to achieve this. Can somebody point me in the right direction?

    Sorry if this is not the place to ask this, please point me to a more suitable place if that is the case.



  • Edit: I know I can just add that beforeCreate to each page.vue to fix this but I am assuming there has to be a way where I don’t have to set this check on every page.



  • In your routes.js you can use the beforeEach() function which will be called every time the user switches routes. It could look something like this:

    routes.beforeEach((to, from, next) => {
       if (to.matched.some(record => record.meta.requiresAuth) && isAuthenticated()) {
         next('/login')
       } else {
         next()
       }
     })
    
     function isAuthenticated() {
       // returns true or false
     }
    

    The meta.requiresAuth is something you can add to a route that needs authentication. Hopefully this helps!



  • @eleina Thanks for answering!

    I am getting 'routes.beforeEach is not a function’
    From what I can find I need to add it as a plugin, but nowhere can I find the content of that plugin…

    Could you help me with that? the rest seems solid so if I have that function working it should all be fine.

    (I also read something about beforeEnter in vue routing, is that also a viable solution?)



  • @Travinns
    in your index.js under src/router folder where you want to check on beforeEach.

    ....
    export default function ({ store }) {
      const Router = new VueRouter({
        scrollBehavior: () => ({ y: 0 }),
        routes,
        mode: process.env.VUE_ROUTER_MODE,
        base: process.env.VUE_ROUTER_BASE
      })
      
      Router.beforeEach((to, from, next) => {
         if (to.matched.some(record => record.meta.requiresAuth)) {
           // this route requires auth, check if logged in
           // if not, redirect to login page.
           if (!auth.loggedIn()) {
             next({
               path: '/login',
               query: { redirect: to.fullPath }
             })
           } else {
             next()
           }
         } else {
           next() // make sure to always call next()!
         }
       })
      return Router
    }
    

    you wanna use beforeEnter if you want to set it per route object. beforeEach is for global navigation guard in each of your route, which is much easier to set up imo, just remember to call next on each conditional/checks you make.



  • @metalsadman thanks for you input!

    Your way also results in an .beforeeach is not a function:

    Uncaught TypeError: routes__WEBPACK_IMPORTED_MODULE_2_.default.beforeEach is not a function

    My full code in index.js (how do I format code here?)

    import Vue from 'vue’
    import VueRouter from 'vue-router’
    import routes from './routes’
    import { AUTH } from ‘…/plugins/firebase’

    Vue.use(VueRouter)
    const Router = new VueRouter({
    mode: process.env.VUE_ROUTER_MODE,
    base: process.env.VUE_ROUTER_BASE,
    scrollBehavior: () => ({ y: 0 }),
    routes
    })

    routes.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
    next({
    path: ‘/login’,
    query: { redirect: to.fullPath }
    })
    } else {
    next()
    }
    } else {
    next() // make sure to always call next()!
    }
    })

    export default Router



  • just like the sample, you put it inside export default function ({...}){ .... your route guards here }
    full index.js code:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import routes from './routes'
    Vue.use(VueRouter)
    
    export default function ({ store }) {
      const Router = new VueRouter({
        scrollBehavior: () => ({ y: 0 }),
        routes,
        mode: process.env.VUE_ROUTER_MODE,
        base: process.env.VUE_ROUTER_BASE
      })
      
      Router.beforeEach((to, from, next) => {
         if (to.matched.some(record => record.meta.requiresAuth)) {
           // this route requires auth, check if logged in
           // if not, redirect to login page.
           if (!auth.loggedIn()) {
             next({
               path: '/login',
               query: { redirect: to.fullPath }
             })
           } else {
             next()
           }
         } else {
           next() // make sure to always call next()!
         }
       })
      return Router
    }
    


  • @metalsadman Taking your sample I now get:
    Uncaught TypeError: routes__WEBPACK_IMPORTED_MODULE_3_.default.beforeEach is not a function.

    Is beforeEach a default Vue feature?



  • @Travinns
    my bad, sorry use capital Router.beforeEach as it was declared at line const Router = ..., it’s a VueRouter feature. edited the sample code.



  • @metalsadman Sorry for the late reply. You suggested solution worked 🙂