How to Add Authentication to a Vue App Using Firebase

Authentication is a critical component of most modern web applications. It allows you to provide a personalized experience for your users, protect sensitive data and functionality, and control access to your app‘s resources. Implementing authentication from scratch can be complex and time-consuming, but thankfully there are powerful tools and platforms that make the process much easier.

In this tutorial, we‘ll look at how to add authentication to a Vue application using Firebase. Vue is a popular progressive JavaScript framework for building user interfaces, while Firebase is a comprehensive mobile and web application development platform that provides a suite of tools and services, including authentication.

By combining Vue and Firebase, you can quickly and easily add secure user authentication to your app without having to build and maintain your own backend. Let‘s get started!

Creating a New Vue Project

First, make sure you have Vue CLI installed. If not, you can install it using npm:

npm install -g @vue/cli

Next, create a new Vue project using the following command:

vue create vue-firebase-auth-demo

When prompted, choose the default preset which includes Babel and ESLint. Once the project is created, navigate into the project directory:

cd vue-firebase-auth-demo

Configuring Firebase

Go to the Firebase Console and create a new project. Give your project a name and click "Continue". On the next screen, you can choose to enable Google Analytics for your project, but it‘s not required for this tutorial so you can click "Create Project" to continue.

Once your Firebase project is ready, click on the web app icon to add Firebase to your web app. Give your app a nickname and click "Register App".

Firebase will provide you with a code snippet to add the Firebase SDK to your app and initialize it with your project‘s configuration. It will look something like this:

// Initialize Firebase
import { initializeApp } from "firebase/app";

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_PROJECT_ID.firebaseapp.com", 
  projectId: "YOUR_PROJECT_ID",
  // ...
};

const app = initializeApp(firebaseConfig);

Copy the firebaseConfig object. Open the main.js file in your Vue project and import Firebase and paste in the configuration:

import { createApp } from ‘vue‘
import App from ‘./App.vue‘
import router from ‘./router‘

import { initializeApp } from "firebase/app";

const firebaseConfig = {
  // Paste your firebaseConfig here
};

initializeApp(firebaseConfig);

createApp(App).use(router).mount(‘#app‘)

Enabling Authentication

Go back to the Firebase Console, click on "Authentication" in the left-hand menu, and then click on the "Sign-in method" tab.

Click on "Email/Password" and toggle the first option, "Enable". This will allow users to sign up and sign in to your app using their email address and a password. Click "Save" to confirm the change.

Creating the Components

Your Vue project will have some default components and routes set up. Let‘s modify those and add some new ones for our authentication flow.

First, rename AboutView.vue to RegisterView.vue. Update the route definition in index.js:

{
  path: ‘/register‘,
  name: ‘register‘,
  component: () => import(‘../views/RegisterView.vue‘)
},

Create a new file called LoginView.vue in the views folder:

<template>
  <div>
    <h2>Login</h2>
    <!-- Login form will go here -->
  </div>
</template>

<script>
export default {
  name: ‘LoginView‘
}
</script>

Update router/index.js to import the LoginView component and add a route for it:

import LoginView from ‘../views/LoginView.vue‘

const routes = [
  {
    path: ‘/‘,
    name: ‘login‘, 
    component: LoginView
  },
  // ...
]

Next, create a DashboardView.vue file in the views folder. This will be the protected page that users can only access after logging in:

<template>
  <div>
    <h2>Dashboard</h2>
    <p>Welcome to the dashboard!</p>
  </div>  
</template>

<script>
export default {
  name: ‘DashboardView‘  
}
</script>

Add a route for the dashboard in router/index.js:

import DashboardView from ‘../views/DashboardView.vue‘

const routes = [
  // ...
  {
    path: ‘/dashboard‘,
    name: ‘dashboard‘,
    component: DashboardView,
    meta: { requiresAuth: true }  
  }
]

Notice the meta property on the dashboard route – this indicates that the route requires authentication. We‘ll use this later to protect the route.

Creating the Login Form

Open LoginView.vue and add a form inside the template with inputs for email and password, and a submit button:

<template>
  <div>
    <h2>Login</h2>

    <form @submit.prevent="login">
      <div>
        <label for="email">Email:</label>
        <input type="email" id="email" v-model="email" required>
      </div>
      <div>
        <label for="password">Password:</label>        
        <input type="password" id="password" v-model="password" required>
      </div>
      <button type="submit">Login</button>
    </form>

  </div>
</template>

<script>
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";

export default {
  name: ‘LoginView‘,
  data() {
    return {
      email: ‘‘,
      password: ‘‘  
    }
  },
  methods: {
    login() {
      const auth = getAuth();
      signInWithEmailAndPassword(auth, this.email, this.password)
        .then((userCredential) => {
          // User logged in successfully
          const user = userCredential.user;
          alert(`Welcome back, ${user.email}!`);
          this.$router.push(‘/dashboard‘);
        })
        .catch((error) => {
          // Handle errors
          const errorCode = error.code;
          const errorMessage = error.message;
          alert(`Error: ${errorCode} - ${errorMessage}`);
        });
    }
  }
}
</script>

In the script section, we import the getAuth and signInWithEmailAndPassword functions from Firebase authentication. The login method is called when the form is submitted – it uses the entered email and password to authenticate the user with Firebase.

If the login is successful, the user is redirected to the dashboard. If there‘s an error, an alert is shown with the error message.

Creating the Registration Form

The registration form will be very similar to the login form. Open RegisterView.vue and replace the contents with the following:

<template>
  <div>
    <h2>Register</h2>

    <form @submit.prevent="register">
      <div>
        <label for="email">Email:</label>
        <input type="email" id="email" v-model="email" required>
      </div>
      <div>
        <label for="password">Password:</label>
        <input type="password" id="password" v-model="password" required>
      </div>
      <button type="submit">Register</button>
    </form>

  </div>
</template>

<script>
import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";

export default {
  name: ‘RegisterView‘,
  data() {
    return {
      email: ‘‘,
      password: ‘‘
    }
  },
  methods: {
    register() {
      const auth = getAuth();
      createUserWithEmailAndPassword(auth, this.email, this.password)
        .then((userCredential) => {
          // User created successfully  
          const user = userCredential.user;
          alert(`Welcome, ${user.email}! Your account has been created.`);
          this.$router.push(‘/‘);
        })
        .catch((error) => {
          // Handle errors  
          const errorCode = error.code;
          const errorMessage = error.message;
          alert(`Error: ${errorCode} - ${errorMessage}`);
        });
    }
  }
}
</script>

The script is nearly identical, except it imports and uses the createUserWithEmailAndPassword function to create a new user account instead of signing in an existing user.

Protecting Routes

To restrict access to the dashboard to only logged in users, we‘ll use Vue Router‘s navigation guards. Open router/index.js and add the following before the createRouter call:

import { getAuth } from "firebase/auth";

const requireAuth = (to, from, next) => {
  const auth = getAuth();
  const user = auth.currentUser;

  if (!user) {
    // User is not logged in
    alert(‘You must be logged in to access this page‘);
    next(‘/‘);
  } else {
    // User is logged in
    next();
  }
};

This defines a requireAuth function that checks if the user is currently logged in using the currentUser property of the Firebase Auth instance. If there is no user, an alert is shown and the user is redirected to the login page. Otherwise, navigation proceeds as normal.

Now apply this guard to the dashboard route:

const routes = [
  // ...
  {
    path: ‘/dashboard‘,
    name: ‘dashboard‘,
    component: DashboardView,
    meta: { requiresAuth: true },
    beforeEnter: requireAuth  
  }
]

Adding a Logout Button

The last piece of functionality we need is the ability for users to log out. We‘ll add a logout button in the App.vue file so that it‘s available on every page once the user is logged in.

Open App.vue and add a logout button and method in the template:

<template>
  <nav>
    <router-link to="/">Login</router-link> |
    <router-link to="/register">Register</router-link> | 
    <router-link to="/dashboard">Dashboard</router-link> |
    <button @click="logout">Logout</button>
  </nav>
  <router-view/>
</template>

<script>
import { getAuth, signOut } from "firebase/auth";

export default {
  methods: {
    logout() {
      const auth = getAuth();
      signOut(auth).then(() => {
        // Sign-out successful
        alert(‘You have been logged out‘);  
        this.$router.push(‘/‘);
      }).catch((error) => {
        // Handle errors
        alert(`Error: ${error.code} - ${error.message}`);  
      });
    }  
  }
}
</script>

The logout method uses the signOut function from Firebase authentication to sign out the current user. Upon successful sign out, the user is redirected back to the login page.

Conclusion

And with that, we have a fully functional authentication system in our Vue app using Firebase! Users can register for an account, log in, access protected pages, and log out. Firebase makes the authentication process straightforward, allowing us to focus on building the rest of our application.

Some potential next steps and improvements could include:

  • Adding form validation and error handling
  • Customizing the look and feel of the authentication forms
  • Implementing password reset functionality
  • Using Firebase UI for pre-built, customizable auth UI components
  • Storing and displaying additional user data in Firestore

I hope this tutorial has been helpful in demonstrating how to add authentication to a Vue app using Firebase. You can find the complete code for this tutorial on GitHub: vue-firebase-auth-demo

If you have any questions or feedback, feel free to leave a comment below. Happy coding!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *