How to Simplify Authorization in Vue.js with Firebase

How to Simplify Authorization in Vue.js with Firebase

Vue.js and other frontend frameworks were designed to tackle the challenges and inefficiencies of traditional web development, making it easier to build modern, interactive interfaces of web applications. Just as these frameworks simplify UI development, other areas of web development have also evolved to become more accessible and efficient. Today, creating a scalable project does not necessarily require an exclusive, expensive, custom-built backend system to handle common server-side challenges.

This is where Backend as a Service (BaaS) solutions come into play, with Firebase standing out as one of the top options. Backed by Google’s cloud infrastructure, Firebase offers a quick, secure, and reliable solution for managing authorization in web apps. In this post, we’ll explore how to simplify authorization with Vue.js Firebase by building a secure and scalable Firebase login and registration system. If you are new to this, consider it a Vue.js Firebase authentication tutorial that will guide you step by step.

A Guide to Setting Up Firebase for Your Vue.js Project

The best part? You can start working with Firebase right after setting up your fresh Vue.js project, and it will work after a few minutes of configuration. To demonstrate the convenience of Firebase Authentication, we will build a basic Vue.js Firebase login and registration form.

How to Simplify Authorization in Vuejs with Firebase, sign up and sign in

How to Set Up Your Firebase Account

Let’s head directly into the Firebase Console. Since Firebase is provided by Google, you’ll only need to sign in with your Google (Gmail) account. You’ll be welcomed with the home page view right after, where you can click + Create a project to start.

The interactive prompts will guide you through setting up:

  • Your new project’s name - as long as it’s free, you can name it anything you want.

  • Google Analytics feature - which is not required for Firebase Authentication to work, so for now, we can skip it. You can enable it later if you are keen to track some information about your future released app.

 How to Set Up Your Firebase Account, Firebase create a project

Setting up User Authentication Method in Firebase Console

Now, let’s set up Authentication in the Console. To enable Firebase login, navigate to  “Build > Authentication” and click it to get to the Firebase Authentication page. Clicking “Get started” will direct you to add your first sign-in method. Once that’s set up, you’re ready to integrate Firebase authentication with Vue in your project.

Setting up Firease Auth

Let’s choose the classic Email/Password method, enable it, and save the settings.

Setting up Auth In Firebase
Setting up Firease Auth with email

You’ll also be able to enable the email link sign-in method (passwordless sign-in), which is one of the new modern ways of securely handling user authentication. For now, we’ll use only the Email/Password method, as any passwordless sign-in method will generally have fewer steps to get the desired result anyway.

This will be enough of setting up the app in the Firebase Console. Let’s get back to our Vue.js project development.

The Best Way to Organize Your Vue.js Project for User Authentication

Let’s walk through the process of integrating Firebase into your Vue.js project to establish a fully functional Firebase authentication system. We’ll start by installing the Firebase SDK, setting up the configuration, and initializing Firebase Auth for your project. By the end of this chapter, you’ll have a solid foundation for handling Firebase Vue.js login and signup functionality, complete with easy-to-use methods for creating and authenticating users.

Install Firebase in Your Vue.js Project

npm install firebase

This single package includes everything we need to establish authentication for our form (and many other Firebase features).

Set Up Your Firebase App

Now, let’s create a file where we can set up our Firebase config for authentication (e.g. /src/plugins/firebase.ts). I strongly encourage you to use TypeScript, although it won’t make that much of a difference for this demo if you prefer to use JavaScript.

To start, let’s initialize the Firebase app in our project.

// plugins/firebase.ts
import { initializeApp } from 'firebase/app';

// example configuration - remember to apply your own!
const firebaseConfig = {
  apiKey: 'YOUR_API_KEY',
  authDomain: 'YOUR_PROJECT_NAME.firebaseapp.com',
  projectId: 'YOUR_PROJECT_NAME',
  storageBucket: 'YOUR_PROJECT_NAME.firebasestorage.app',
  messagingSenderId: '0000000000000',
  appId: '0:000000000:web:000000000000000',
};

const app = initializeApp(firebaseConfig);

To find all of the above configuration data for your project:

  1. Jump into your project in the Firebase Console.

  2. Click on the gear icon and choose “Project settings” (right under the Firebase logo, top left corner).

  3. On the Project settings page, scroll down to the Your apps section. You will see that no apps are in your project yet, so we have to create one.

  4. Click on the web icon “</>” and add a nickname for your project.

  5. Click “Register app.”

web icon nickname Firebase

After that, Firebase will give you the exact setup you need to copy and paste into the /src/plugins/firebase.ts file!

REMEMBER: This setup data (especially your apiKey) is sensitive, so do not push it into any remote public repository. Instead, you can use Environment Variables.

Initialize the Firebase Auth Instance for Your App

We are almost ready to create our first user! Once Firebase is initialized, set up the Firebase Vue.js login and signup methods using firebase/auth. With a new Firebase App added to both the Firebase Console and our Vue.js project, let’s start with Auth initialization. 

// plugins/firebase.ts
import { initializeApp } from 'firebase/app';
import {
  getAuth, // provides the Auth instance
  createUserWithEmailAndPassword, // sign-up method
  signInWithEmailAndPassword, // sign-in method
} from 'firebase/auth';

const firebaseConfig = {
  apiKey: 'YOUR_API_KEY',
  authDomain: 'YOUR_PROJECT_NAME.firebaseapp.com',
  projectId: 'YOUR_PROJECT_NAME',
  storageBucket: 'YOUR_PROJECT_NAME.firebasestorage.app',
  messagingSenderId: '0000000000000',
  appId: '0:000000000:web:000000000000000',
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app); // initialize Auth

The Auth is now fully set up to be used! In the above example, we also imported two methods, which we will connect to our SIGN IN and SIGN UP form submit buttons.

Create Login and Register Functions Using Firebase Auth

As our form design hints and as we set up the Authentication in Firebase Console, we will have to provide email and password strings from the form to the firebase/auth imported methods.

Let’s create some wrapping functions to simplify function names and add some console logs to check if our configuration is working as expected or giving us any errors.

// plugins/firebase.ts
import { initializeApp } from 'firebase/app';
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
} from 'firebase/auth';

const firebaseConfig = {
// ...
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

export const createUser = async (email: string, password: string) => {
  try {
    const userCredential = await createUserWithEmailAndPassword(auth, email, password);
    console.log('User created:', userCredential.user);
  } catch (error) {
    console.error('Error creating user:', error);
  }
};

export const login = async (email: string, password: string) => {
  try {
    const userCredential = await signInWithEmailAndPassword(auth, email, password);
    console.log('User signed in:', userCredential.user);
  } catch (error) {
    console.error('Error signing in:', error);
  }
};

Now, with the ready createUser() and login() functions, we can jump into the form and use them!

Creating the Login and Registration Form with Firebase

You can set up your form with any Vue.js tools and style it however you like. I skipped using UI libraries for demo purposes so that we could dive into Firebase as soon as possible with the simplest design. We’re also skipping form validation, as it isn't directly related to using Firebase for authentication, and the tools won’t affect each other. 

With the above ready, let’s build a simple Vue.js Firebase login and registration form. Here’s an example of how a template and script of such a form could look like:

// App.vue
<template>
  <main class="content">
    <form @submit.prevent class="login-form">
      <input
        v-model="email"
        type="email"
        placeholder="Your email..."
        class="login-input" />
      <input
        v-model="password"
        type="password"
        placeholder="Your password..."
        class="login-input"
      />

      <div class="buttons">
        <button type="submit" @click="signIn" class="submit-button">
          Sign in
        </button>
        <button type="submit" @click="signUp" class="submit-button">
          Sign up
        </button>
      </div>
    </form>
  </main>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { login, createUser } from './plugins/firebase';

const email = ref<string>('');
const password = ref<string>('');

const signIn = async () => {
  if (!email || !password) {
    // add your own form validation logic
    return;
  }
  await login(email.value, password.value);
};

const signUp = async () => {
  if (!email || !password) {
    // add your own form validation logic
    return;
  }
  await createUser(email.value, password.value);
};
</script>

Let’s break it down - we have:

  1. Added two input fields for the user to provide email and password

  2. Connected the input fields to reactive ref() with the help of v-model

  3. Created two new functions to pass email and password values into imported Firebase functions

  4. We added two buttons and connected their @click event to trigger signIn and signUp functions.

So, it looks like the Auth is ready to be tested! Let’s create a new user by providing an email and password and then clicking the SIGN-UP button.

Setting up Firease Auth creating new user

Afterward, you should see either an error with a meaningful message about what went wrong (e.g., a too-short password) or, as in the above screenshot, the data of your newly created user! You can also check the user now in the Firebase Console:

Firebase console

Hey, we created the user, but this Vue interface has not yet been prepared to react to user Firebase authentication state changes. We’ve seen a console.log with the user’s data, but that’s not enough for the user to understand that he successfully signed in.

Implementing Authentication State Management with Firebase

So, how do we check for user state changes? Firebase provides an excellent observer function for changes to the user's sign-in state called onAuthStateChanged. To use it, all we need is to import it and provide our app from plugins/firebase.ts

// App.vue
// ...
import { auth } from './plugins/firebase'; // remember to export it first!
import { onAuthStateChanged } from 'firebase/auth';
// ...
onAuthStateChanged(auth, (user) => {
  // initially, let it clear the form from the input whenever the state changes
  email.value = '';
  password.value = '';
});

Thanks to onAuthStateChanged, we now have a place to put our state change handling logic. Additionally, the function we pass is given a user parameter, which is exactly the same object as the user we got from the createUserWithEmailAndPassword() function (the one we saw in the browser’s console).

So now, whenever the user object’s state changes, we can adjust the state of our Vue app accordingly. To save the state after each change, let’s introduce global state management with Pinia to our application. In case you’re interested in best practices of Vue.js Modular state management, we’ve covered this subject in one of our earlier articles. 

Meanwhile, let’s create a new store file:

// stores/userStore.ts
import { ref, computed } from 'vue';
import { defineStore } from 'pinia';
import type { User } from 'firebase/auth';

export const useUserStore = defineStore('user', () => {
  // here we'll save our user object
  const user = ref<User | null>(null);

  // if user object exists - we're logged in, and if not - we're not :) 
  const isLoggedIn = computed<boolean>(() => !!user.value);

  // an example state information to display in the app
  const userName = computed<string | null>(() => { 
    if (user.value) {
      return user.value?.displayName || user.value?.email
    }
    return null;
  });

  // we will use setUser method to save user object on each state change
  const setUser = (userData: User | null) => (user.value = userData);

  return { user, isLoggedIn, userName, setUser };
});

Now, let’s use the store to save the user information after signing in:

<template>
  <main class="content">
    <form @submit.prevent class="login-form">
      <!-- changing the UI depending on isLoggedIn value -->
      <h2 v-if="userStore.isLoggedIn">
        <!-- displaying userName to the user - a clear state change sign -->
        Welcome, {{ userStore.userName }}
      </h2>
      <template v-else>
        <input v-model="email" type="email" placeholder="Your email..." class="login-input" />
        <input
          v-model="password"
          type="password"
          placeholder="Your password..."
          class="login-input"
        />
      </template>

      <div class="buttons">
        <button type="submit" @click="signIn" class="submit-button">
          Sign in
        </button>
        <button type="submit" @click="signUp" class="submit-button">
          Sign up
        </button>
      </div>
    </form>
  </main>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { auth, login, createUser } from './plugins/firebase';
import { useUserStore } from './stores/userStore';
import { onAuthStateChanged } from 'firebase/auth';

// initalizing the store composable
const userStore = useUserStore();

const email = ref<string>('');
const password = ref<string>('');

const signIn = async () => {
  if (!email || !password) {
    return;
  }
  await login(email.value, password.value);
};

const signUp = async () => {
  if (!email || !password) {
    return;
  }
  await createUser(email.value, password.value);
};

onAuthStateChanged(auth, (user) => {
  // saving the user to the store
  userStore.setUser(user || null);
  email.value = '';
  password.value = '';
});
</script>

Let’s break it down:

  1. After typing the user credentials into the form and clicking the SIGN IN button, we will change the user state, which will trigger the onAuthStateChanged observer.

  2. The callback function we pass into the observer will save the user data to the store with the setUser() function.

  3. Thanks to Vue reactivity, the new user state changes all the other computed values from the store, such as isLoggedIn and userName.

  4. We use those values in the App.vue file’s template to change the UI, which, after clicking the SIGN IN button, now looks like this:

Firebase sign in button

And that’s it! Now, our app is set up entirely to handle the user Authentication state!

Unlike traditional backend solutions, we eliminate the need to store sensitive information (such as tokens) in the browser or manage sessions through conventional methods. Firebase takes care of these tasks seamlessly, right out of the box.

Logging Out Users and Handling Session Expiry

What we needed from Firebase up to this point was only four functions:

  • getAuth

  • createUserWithEmailAndPassword

  • signInWithEmailAndPassword

  • onAuthStateChanged

Yet, still, even though we visually and dynamically represent the Auth state change to the user now, you probably already noticed that the UI is still not perfect. It would be nice to change the buttons to a single SIGN OUT button, right?

Set Up the Logout Function in Firebase

It will be as easy as all of what we previously did. Let’s set up the new logout function:

// plugins/firebase.ts
import { initializeApp } from 'firebase/app';
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut, // Firebase function to log out the user
} from 'firebase/auth';

const firebaseConfig = {
// ,,,
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

export const createUser = async (email: string, password: string) => {
// ...
};

export const login = async (email: string, password: string) => {
// ...
};

// new logout function
export const logout = async () => {
  try {
    await signOut(auth);
    console.log('User signed out');
  } catch (error) {
    console.error('Error signing out:', error);
  }
};

In this case, as we did before, we do not have to put any params into the function, like email and password.

In the template of the App.vue file, let’s add a condition to display different buttons, and let’s connect the new logout function to the @click event of the new button:

// App.vue
// ...
<div v-if="userStore.isLoggedIn" class="buttons">
  <button type="submit" @click="logout" class="submit-button">Sign out</button>
</div>

<div v-else class="buttons">
  <button type="submit" @click="signIn" class="submit-button">
    Sign in
  </button>
  <button type="submit" @click="signUp" class="submit-button">
    Sign up
  </button>
</div>

// ...

// logout function import
import { auth, login, createUser, logout } from './plugins/firebase';

The logout() function takes no parameters, so we can skip wrapping it into a handling function as we previously did with signIn() and signUp().

Now we should see:


Firebase sign out button

As expected, if we click the SIGN-OUT button, we log out, and the interface changes into its initial state:

Firebase log out view

Manage Session Expiry in Firebase Authentication

Certain highly secure applications require users to re-authenticate after a specific period. Unfortunately, as the Firebase documentation states, “Firebase Authentication sessions are long-lived,” which doesn’t make session expiry a default behavior for the tool. There are only a few scenarios in which the session expires automatically by Firebase SDK:

  • When the user is deleted

  • When the user is disabled

  • When major user data is changed, such as password reset or email change

The good news is there are many custom ways to force such behavior. To pick an example, we’ll have to dive into the Firebase Realtime Database and its Security Rules, which we’ll do in another incoming post.

Bonus: Add Google Sign-In to Your Firebase Authentication Setup

Since we know how to Authenticate with email and password, let’s briefly try another provider to quickly recap how fast and efficient it is to use Firebase Authentication.

Let’s integrate Google Sign-In for a modern Firebase Vue.js login and signup experience. In Firebase Console, choose the Google sign-in method, enable it, give it a name, select support email, and save the setting:

Google Sign-In in Firebase Authentication Setup

Now we can dive back into our Vue project:

// plugins/firebase.ts
import { initializeApp } from 'firebase/app';
import {
  getAuth,
  GoogleAuthProvider, // provider to generate Google Auth
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signInWithPopup,
  signOut,
} from 'firebase/auth';

const firebaseConfig = {
// ...
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

// important to pass to signInWithPopup method
const provider = new GoogleAuthProvider();

export const createUser = async (email: string, password: string) => {
// ...
};

export const login = async (email: string, password: string) => {
// ...
};

export const loginWithGoogle = async () => {
  try {
    // the same logic as with email and password method
    const userCredential = await signInWithPopup(auth, provider);
    console.log('User signed in:', userCredential.user);
  } catch (error) {
    console.error('Error signing in:', error);
  }
};

export const logout = async () => {
// ...
};

In the App.vue file, let’s import the function and add a new button to trigger the function:

// template
<button type="submit" @click="loginWithGoogle" class="submit-button">
  Sign in with Google
</button>

// script
import { auth, login, createUser, loginWithGoogle, logout } from './plugins/firebase';

Now, we have a fully functioning login button to open a new tab with a Google Auth page. 

login button to open a new tab with a Google Auth page

Discover the Simplicity of Firebase Authentication with Vue.js

As we’ve seen throughout this guide, Firebase Authentication and Vue.js work seamlessly together to provide a secure, scalable, and user-friendly solution for managing user authorization. With Firebase’s out-of-the-box features like email/password authentication, user state management, and support for third-party providers like Google, you can quickly build robust authentication systems without diving into complex backend logic.

By leveraging Vue.js for dynamic UI updates and Firebase for authentication services, you can focus more on delivering a smooth user experience and less on server-side setup. Whether you’re creating a simple login page or scaling to support thousands of users, Firebase and Vue.js simplify the process, helping you get up and running with minimal configuration.

Patryk Wawrzeński
Patryk Wawrzeński
JavaScript Developer at Monterail
Patryk is a front-end developer with a passion for Vue.js and its simplicity. With a background in commercial graphics, he brings a pixel-perfect approach to creating easily scalable and maintainable software. He combines design precision with clean and efficient code to deliver functional and aesthetically pleasing products.