0

I'm using Firebase, FirebaseUI, Vue, vue router, and vuex.

  1. I have a home view ('/') that shows a "Log In" button. At this point, the vuex state has a user variable set to null. When I click on it, it takes me to my login view ('/login'). Suspicious thing: Looking at Vue DevTools, home remains the active view.
  2. I use FirebaseUI to handle my logging in stuff. Once successfully logged in, my site redirects to a console view ('/console') which has a "Log Out" button, and the user variable in vuex is set to an object. Suspicious thing: Looking at Vue DevTools, login is now the active view.
  3. Clicking the "Log Out" button still keeps me in the '/console/ vue. Vuex has a user variable set to null.
  4. Refreshing the page automatically redirects me to the '/login' view.

I'm wondering if the fact that the active view isn't correct is the root of this issue. I found other people with the same problem saying they weren't using the webpack correctly by importing their App.vue file as a js, but I'm importing it as a .vue file in my main.js file.

I'm also suspicious of the FirebaseUI uiConfig in my Login.vue file. I have to set signInSuccessUrl: '#/console', (note the #). If I don't have the #, it redirects me to home (url = http://localhost:8081/console#/).

App.Vue

<template>
  <v-app>
    <v-content>
      <router-view></router-view>
    </v-content>
  </v-app>
</template>

<script>
export default {
  name: 'App',

  methods: {
    setUser: function() {
      this.$store.dispatch('setUser');
    }
  },
  data: () => ({
    //
  }),
  created () {
    // when the app is created run the set user method
    // this uses Vuex to check if a user is signed in
    // check out mutations in the store/index.js file
    this.setUser();
  },
};
</script>

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify'

import { store } from './store/index';

// Firebase App (the core Firebase SDK) is always required and
// must be listed before other Firebase SDKs
import firebase from "firebase/app";

// Add the Firebase services that you want to use
import "firebase/auth";
import "firebase/firestore";

var firebaseConfig = {
  // I'm editing this part out
};

// Initialize Firebase
firebase.initializeApp(firebaseConfig);

// Check before each page load whether the page requires authentication/
// if it does check whether the user is signed into the web app or
// redirect to the sign-in page to enable them to sign-in
router.beforeEach((to, from, next) => {

  const currentUser = firebase.auth().currentUser;
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);

  if (requiresAuth && !currentUser) {
    next('/login');
  } else if (requiresAuth && currentUser) {
    next();
  } else {
    next();
  }
});

// Wrap the vue instance in a Firebase onAuthStateChanged method
// This stops the execution of the navigation guard 'beforeEach'
// method until the Firebase initialization ends
firebase.auth().onAuthStateChanged(function (user) {
  user;
  new Vue({
    el: '#app',
    store,
    router,
    vuetify,
    render: h => h(App)
  });
});

router\index.js

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

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/about',
    name: 'about',
    component: () => import('../views/About.vue')
  },
  {
    path: '/tryit',
    name: 'tryit',
    component: () => import('../views/TryIt.vue')
  },
  {
    path: '/pricing',
    name: 'pricing',
    component: () => import('../views/Pricing.vue')
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('../views/Login.vue')
  },
  {
    path: '/console',
    name: 'console',
    component: () => import('../views/Console.vue'),
    meta: {    requiresAuth: true   }
  }
]

const router = new VueRouter({
  routes
})

export default router

store\index.js

import Vue from 'vue';
import Vuex from 'vuex';
import Firebase from 'firebase';

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    user: null
  },
  getters: {
    getUser: state => {
      return state.user;
    }
  },
  mutations: {
    setUser: state => {
      state.user = Firebase.auth().currentUser;
    },
    logoutUser: state => {
      state.user = null;
    }
  },
  actions: {
    setUser: context => {
      context.commit('setUser');
    },
    logoutUser: context => {
      context.commit('logoutUser');
    }
  }
});

Login.vue

<template>
  <div class="login">
    <NavbarAnon />

    <!-- The surrounding HTML is left untouched by FirebaseUI.
     Your app may use that space for branding, controls and other customizations.-->
    <h1>Welcome to My Awesome App</h1>
    <div id="firebaseui-auth-container"></div>
    <div id="loader">Loading...</div>


  </div>
</template>

<script>
// @ is an alias to /src
import NavbarAnon from '@/components/layout/NavbarAnon';
import 'firebaseui/dist/firebaseui.css';

// Firebase App (the core Firebase SDK) is always required and
// must be listed before other Firebase SDKs
var firebase = require("firebase/app");

// Add the Firebase products that you want to use
require("firebase/auth");
require("firebase/firestore");

var firebaseui = require('firebaseui');

export default {
  name: 'login',
  components: {
    NavbarAnon
  },
  mounted() {
    // Initialize the FirebaseUI Widget using Firebase.
    let ui = firebaseui.auth.AuthUI.getInstance();
    if (!ui) {
      ui = new firebaseui.auth.AuthUI(firebase.auth());
    }

    var uiConfig = {
      callbacks: {
        signInSuccessWithAuthResult: function(authResult, redirectUrl) {
          // User successfully signed in.
          // Return type determines whether we continue the redirect automatically
          // or whether we leave that to developer to handle.
          authResult + redirectUrl;
          return true;
        },
        uiShown: function() {
          // The widget is rendered.
          // Hide the loader.
          document.getElementById('loader').style.display = 'none';
        }
      },
      // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
      signInFlow: 'popup',
      signInSuccessUrl: '#/console',
      signInOptions: [
        // Leave the lines as is for the providers you want to offer your users.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.EmailAuthProvider.PROVIDER_ID
      ],
      // Terms of service url.
      tosUrl: '<your-tos-url>',
      // Privacy policy url.
      privacyPolicyUrl: '<your-privacy-policy-url>'
    };

    // The start method will wait until the DOM is loaded.
    ui.start('#firebaseui-auth-container', uiConfig);
  }
};
</script>

In the HeaderBar.vue (which has the logout button):

methods: {
      signOutUser() {
        //this.$emit("trying to sign out user");
        firebase.auth().signOut().then(function() {
          // Sign-out successful.
          this.$store.dispatch('logoutUser');
          this.$route.push('/');
        }).catch(function(error) {
          //this.$emit("signout error", error);
          error;
          // An error happened.
        });
      }
    }
Emma
  • 51
  • 1
  • 7
  • 2
    in Logout you use this.$route.push('/'); why not this.$route.push('/login'); – Valera Kvip Jan 25 '20 at 22:07
  • I didn't have any particular reason to. Changing to this.$route.push('/login') doesn't change anything though. – Emma Jan 25 '20 at 22:21
  • `console.log(this)` inside `firebase.auth().signOut().then(function() { console.log(this)}` and you will see that `this` doesn't point to what you think it does. Please read: https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – AT82 Jan 26 '20 at 17:37

0 Answers0