Vue Firebase UI: Create Login Page [Facebook/Google Auth]

Last modified on May 11th, 2021
Raja Tamil
Firebase Vue.js

In this Firebase + Vue tutorial, you are going to learn the QUICKEST way to implement a login system to your vue app using FirebaseUI including OAuth providers Facebook Sign-in, Google Sign-in and Email/Password Sign-in without writing any UI related code what so ever.

If you look at most of the web / mobile login screens, you will see the three most common sign-in methods such as Email and Password, Facebook and Google. 

That’s what is exactly covered in this article!

Before further ado, let’s get started!

Setting up Starter VueJs Project

I have already created a sample vue starter project and downloaded it so that you can follow along if you want. I am also assuming that you have node installed on your computer.

Once it’s downloaded, open up the terminal/command prompt and cd to the starter project folder and issue npm install command which will install dependencies for the project.

After that, run the application using npm run dev command.

Then, go to the localhost and you can see the app is running similar to the screenshot below.

As you can see this sample app has three navigation items: home (/), profile (/profile) and login (/login).

Pretty straight forward!

Add Firebase to the Web App

The FIRST step is you need to install firebase package to the project.

npm install firebase --save

Then, go to Firebase and create a project if you have not already done so.

After that…

Go ahead and obtain the configuration code from the Firebase dashboardProject Overview (at the top left) → click the gear ⚙ icon → click Project Settings.

Then, scroll to the bottom → under the Firebase SDK snippet section → choose Config option and copy the code.

If you haven’t seen the configuration page, you need to register the app by clicking </> web icon which will open up the window. Follow the instructions to complete the registration process.

Once you have registered, then you can come back to the above location and obtain the firebase configuration code.

Next, I am going to initialize Firebase.

To do that, go to main.js file and import firebase at the top.

import firebase from 'firebase'

After that, paste the configuration code that you copied earlier.

const firebaseConfig = {
  apiKey: "*****",
  authDomain: "firebaseUIAuth-*****.firebaseapp.com",
  databaseURL: "https://****-709a3.firebaseio.com",
  projectId: "firebaseUIAuth-709a3",
  storageBucket: "",
  messagingSenderId: "2547636***397",
  appId: "1:254763***397:web:***c15c671b5c"
};

Make sure to obtain the config code from your firebase project as the above code will not work for your project.

Finally, initialize firebase.

firebase.initializeApp(firebaseConfig);

If you run the app at this point, everything should work as it did previously.

Sign in with Facebook Using FirebaseUI

For the FIRST step, you need to install firebaseui packages to the project.

npm install firebaseui --save

The NEXT step would be to import firebase, firebaseui and firebaseui.css packages to the Login.vue component.

import firebase from "firebase";
import firebaseui from "firebaseui";
import "firebaseui/dist/firebaseui.css";

Then, create an element with an ID inside <template> which is the container element where the Sign-in with Facebook button will appear.

<section id="firebaseui-auth-container"></section>

After that, Instantiate firebaseui object by passing firebase.auth() and store it in a variable called ui inside the mounted() function like the code below.

As you can see in the below code, I have defined a Javascript object called uiConfig which will have two properties.

mounted() {
        var ui = new firebaseui.auth.AuthUI(firebase.auth());
        var uiConfig = {
            signInSuccessUrl: "/profile",
            signInOptions: [firebase.auth.FacebookAuthProvider.PROVIDER_ID]
        };
        ui.start("#firebaseui-auth-container", uiConfig);
    }

The first one is the signInSuccessUrl and set its value of a /profile route. This property will take it to the profile page upon successful login.

The second property is signInOption which is an array in which I have a Facebook button in there for now. This is the place where you will be adding more buttons later.

Finally, invoke the start() method on the ui object and pass #firebaseui-auth-container as a first argument and uiConfig as a second.

Now, you can see the Sign-in with Facebook button on the login page.

You can configure with more options than given inside uiConfig object. For example, if you want the sign in flow to be a popup window you can set signInFlow: “popup”. Find out more here.

Nice!

But there is a problem…

If I switch to the home or profile page and come back to the login page, I do not see the Sign-in with Facebook button and also will get an error on the browser console.

"Error: An AuthUI instance already exists for the key

This is because I am running a single page vue application, so it’s trying to instantiate firebase Auth UI object every single time when I go to /login route.

To fix that, I can easily check to see if firebaseui object is instantiated or not before creating a new instance.

So, replace the code inside the mounted() method

from

var ui = new firebaseui.auth.AuthUI(firebase.auth());

to

let ui = firebaseui.auth.AuthUI.getInstance();
if (!ui) {
    ui = new firebaseui.auth.AuthUI(firebase.auth());
}

That would fix AuthUI instance issue!

Now, let’s click the button and see what’s happening…I got a warning message.

The Identity provider configuration is not found

This message leads to the next step which is enabling Facebook sign-in provider on Firebase.

Go to Firebase Console → Authentication Sign-in methodsFacebook.

Then, click the pencil icon on the right side of the Facebook row which will bring the pop-up window and enable the switch at the top right and hit save.

At this stage, Firebase does not let you save as it needs App ID and App Secret from the Facebook Developer console to complete the setup.

Firebase Console Facebook Setup Screen

To obtain App ID and App Secret from Facebook, go to developer.facebook.com and log in.

At the top right, click My Apps and hit Create App from the drop-down menu which will bring a dialog box.

facebook-allows-app-use-data-upon-permission

Enter a display name that will be shown to the users when they are redirected to Facebook after clicking the Sign-in with Facebook button for the first time like in the screenshot below.

Then hit Create App ID.

After that, go to the Facebook app dashboard choose settings (from the sidebar) Basics

Once you have the App ID and App Secret, head over to Firebase Console Authentication Sign-in Methods click the edit icon on the right next to Facebook and add the App ID and App Secret there.

Before hitting save, copy the OAuth redirect URI.

The URI that you have copied from Firebase will be added to the Facebook App in order to complete the process.

To do that, Go to Facebook App Dashboard Product Add New by clicking the + sign and choose Facebook Login by hitting the Set Up button.

facebook-new-product-login
facebook-new-product-login

Once the Products is created, Choose Facebook Login under Products section Settings Find Valid OAuth Redirect URIs and paste the redirect URL that was copied from Firebase console in here and hit save changes.

If you want to go live, you must provide Add Privacy Policy Link and Enable Facebook App to Live.

All Set!

Now, go back to the login page and click the Sign in with Facebook button, and it will be redirected to the profile page indicating you have successfully logged in with Facebook. 🙂

Let’s add some code to show the user account information on the profile page upon successful login.

The first step is to import firebase on the profile page.

import firebase from "firebase";

Then, create a property called user and set its initial value null inside data().

data() {
       return {
           user: null
     };
 },

After that, define firebase onAuthStateChanged inside created() function checks to see if a user is logged in or not.

created() {
       firebase.auth().onAuthStateChanged(user => {
           if (user) {
               this.user = user;
           }
       });
   }

As you can see, I could use Vuex store for a global variable for user data, but for simplicity sake, I will be using onAuthStateChanged method on the profile component to get user data.

Now, we have logged in user data, add the HTML code inside the template after heading to show the profile information.

<div class="card horizontal" style="max-width:400px;margin:0 auto;" v-if="user">
    <div class="card-image" style="margin-top:25px;margin-left:10px;"> <img :src="user.photoURL"
            style="width:75px;height:75px;border-radius:50%;border:4px solid #333" /> </div>
    <div class="card-stacked">
        <div class="card-content">
         <p> name: <strong>{{user.displayName}}</strong><br />email:<strong>{{user.email}}</strong><br/>uid:
                <strong>{{user.uid}}</strong> <br />provider: <strong
                    class="teal-text">{{user.providerData[0].providerId}}</strong> </p>
        </div>
    </div>
</div>

At this stage, your profile page will look like this:

facebook-signin-oauth-profile-firebase
facebook-signin-oauth-profile-firebase

Let’s add a sign-out button before adding other providers.

Go ahead and open up NavBar.vue and add logout as a third button.

<li>
   <a @click="signoutButtonPressed">Logout</a>
</li>

Then, declare signoutButtonPressed() function inside methods:{} object.

methods: {
    signOut(e) {
        e.stopPropagation();
        firebase.auth().signOut();
        this.$router.push({
            name: "Login"
        });
    }
}

In this function, I have invoked signout() method. Once the user is signed out it will be redirected to the login page.

Pretty straight forward!

I know it would be weird to see login and logout buttons at the same time, I am going to be fixing that later in this article. Let’s move on to login with google.

Sign-in with Google using FirebaseUI

STEP 01: Go to the Firebase Console Dashboard Authentication section Sign-in Methods Tab, enable Google Provider by clicking the pencil icon on the right side.

STEP 02: Go back to Login.vue inside the signInOptions array add the Google Provider code under Facebook.

signInOptions: [
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.GoogleAuthProvider.PROVIDER_ID
]

STEP 03: That’s it!

I find this is one of the easiest ways to add Google Authentication into the project with very little time. 🙂

Login with Email and Password using FirebaseUI

STEP 01: Go to the Firebase Console Dashboard Authentication section Sign-in Methods Tab, enable Email by clicking the pencil icon on the right side.

STEP 02: Go back to Login.vue inside the signInOptions array add the Google Provider code under Facebook.

signInOptions: [
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
]

STEP 03: Now you can see the Sign in with email Button when you refresh the Login.vue page.

When you click the Sign in with email button, it will redirect to the Account Chooser page where you can see all other previously logged-in accounts with different providers.

If you’re trying to log in for the first time, it will take you to FirebaseUI default email form page.

It will also validate on the fly whether the email is already registered with any auth provider and will redirect it to an appropriate page to complete the sign-in process.

If it’s new, it will ask you to add your name and password to create a brand new firebase account.

As you can see, all the FirebaseUI has already set UI in place so you do not have to write a single line of code.

You may wonder what happens if a user wants to log in with a different provider at different time.

The answer is Yes…FirebaseUI allows users to login with different OAuth providers with a single email and links them all under one firebase account.

There are a couple of UX (user experience) issues with this vue.js application.

Protect Vue Routes Upon Authentication

The first issue is to show and hide navigation items based on whether the user is logged in or not.

At the navigation bar, let’s hide the profile and log out button when the user is not signed and hide the login button when a user is signed in.

To do that, go to NavBar.vue component and import firebase. import firebase from “firebase”.

import firebase from "firebase";

After that, declare a property called user inside data() similar to what I did with profile.vue earlier.

data() {
    return {
        user: null
    };
},

Then, invoke onAuthStateChange() method of firebase inside created() and set the provided user value to the user property.

created() {
    firebase.auth().onAuthStateChanged(user => {
        this.user = user;
    });
},

Finally, show and hide navigation items based on the user authentication state using v-show directive.

<li v-show="!user">
    <router-link to="/login">Login</router-link>
</li>
<li v-show="user">
    <router-link to="/profile">Profile</router-link>
</li>
<li v-show="user"> <a @click="signoutButtonPressed">Logout</a> </li>

At this stage, your user navigation should look like this if the user is not logged in.

When the user is logged in, the screen should look like this…

Navigation looks perfect.

But…there will be another issue which is…

Even though the profile navigation is hidden when a user is not logged in, you can go to the profile page by typing it in the browser.

To fix that, you need to have a Navigation Guard on the index.js file inside the router folder.

The way you create Navigation Guard globally is by invoking beforeEach() method on router object. This method will be called every time you go to any route in the application.

I am going to import firebase as I need to check the user login status inside the beforeEach() method.

import firebase from 'firebase'

As mentioned earlier, beforeEach() is a method of router object, so I have to assign a route object to a variable called router.

let router = new Router({
    mode: 'history',

    routes: [{
        path: '/profile',
        name: 'Profile',
        component: Profile,
        meta: {
          auth: true
        }

      },
      {
        path: '/login',
        name: 'Login',
        component: Login,
        meta: {
          guest: true
        }

      },
      {
        path: '/',
        name: 'Home',
        component: Home,

      }
    ]

  },

)

You can add mode: 'history' property to the router object for a clean URL as it gets rid of the # sign from it.

Add the meta-objects to the routes so that we can use them inside beforeEach() methods.

As you can see, I have added a meta-object to two routes which are for /profile (auth:true) so that only authenticated users can go there,…

and …guest:true for /login route so that only non-authenticated users can go there.

Let’s declare beforeEach().

The first if statement checks to see if the trigged route has a meta-object with the property auth set to true.

If yes, invoke firebase onAuthSatateChanged method and if there is a user then go to the same route using next() method. If not, redirect to the /login route.

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

  if (to.matched.some(record => record.meta.auth)) {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        next()
      } else {
        next({
          path: "/login",
        })
      }
    })
  } else if (to.matched.some(record => record.meta.guest)) {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        next({
          path: "/profile",
        })
      } else {
        next()
      }
    })

  } else {
    next()
  }

})

export default router

The same way, check to see if the triggered route has a meta-object with a property guest set to true.

If yes, invoke firebase onAuthSatateChanged method and if there is a user then redirect to the /profile route. If not, go to the same route using next() method.

That’s it!

At this stage, you will have a fully functional User Authentication system including OAuth providers such as Facebook, Google using FirebaseUI . 🙂

You can view the full source code here.

What are the other OAuth providers that you want to include in your login page? Let me know so that I can add it later.