Unlock the Power of Firebase Authentication in Your Next.js App

The Importance of Authentication in Web Applications

In today’s digital landscape, authentication is a crucial feature that many developers have had to implement in their web applications. Fortunately, libraries like Firebase have made this task easier by offering a range of built-in functionalities.

What is Firebase?

Acquired by Google in 2014, Firebase is a platform that offers a suite of products, including a Realtime Database, Authentication, and Cloud Messaging. These products enable developers to create and run applications quickly and efficiently.

Creating a Firebase Account and Project

Before you start coding, you’ll need a Firebase account. Head over to the Firebase website to create one. Once you’ve set up your account, create a project and an app to get your API keys. Enable the sign-in methods you want to use, such as traditional email/password authentication.

Setting Up Your Next.js Project

Create a new Next.js project using the following command:

npx create-next-app my-app

This will set up everything automatically for you. Add your Firebase API keys to your project by creating a .env.local file. Install the Firebase library and other dependencies, such as reactstrap and bootstrap, for styling.

Creating a Firebase Instance in Next.js

Create a lib directory in your project root folder and add a firebase.js file. Use your API keys to create a Firebase instance, focusing on authentication. Create an authUser variable to access throughout your app, which will be helpful for user management and redirecting routes accordingly.


import firebase from 'firebase/app';
import 'firebase/auth';

const firebaseConfig = {
  apiKey: process.env.API_KEY,
  authDomain: process.env.AUTH_DOMAIN,
  projectId: process.env.PROJECT_ID,
};

firebase.initializeApp(firebaseConfig);

const auth = firebase.auth();
let authUser = null;

export { auth, authUser };

Listening for Firebase Changes

Use React’s useEffect to listen for state changes in Firebase. Create a useFirebaseAuth.jsx file in the lib directory and add a function to format the user depending on your needs. Set the authUser variable and use a loading variable to indicate whether Firebase is fetching data or not.


import { useState, useEffect } from 'eact';
import { auth } from './firebase';

const useFirebaseAuth = () => {
  const [authUser, setAuthUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    auth.onAuthStateChanged((user) => {
      if (user) {
        setAuthUser(user);
      } else {
        setAuthUser(null);
      }
      setLoading(false);
    });
  }, []);

  return { authUser, loading };
};

export default useFirebaseAuth;

Creating a User Context

To access the authUser and loading variables throughout your app, use the Context API. Create a context/AuthUserContext.jsx file and add a default value for authUser as null and loading as true. Then, create a custom hook, useAuth, to access the current context value.


import { createContext, useState } from 'eact';

const AuthUserContext = createContext({
  authUser: null,
  loading: true,
});

const useAuth = () => {
  const context = useContext(AuthUserContext);
  if (!context) {
    throw new Error('useAuth must be used within an AuthUserProvider');
  }
  return context;
};

export { AuthUserContext, useAuth };

Creating Protected Routes

Protected routes are pages or sections of your app that should only be accessed by certain users. Get the authUser and loading variables from your custom useAuth() hook and check if the user is logged in. If not, redirect them to the login page.


import { useRouter } from 'next/router';
import useAuth from '../context/AuthUserContext';

const ProtectedRoute = () => {
  const { authUser, loading } = useAuth();
  const router = useRouter();

  if (loading) {
    return
Loading…
;
  }

  if (!authUser) {
    router.push('/login');
  }

  return
Welcome, {authUser.email}!
;
};

export default ProtectedRoute;

Adding Login, Sign-up, and Sign-out Functionalities

Use Firebase’s built-in functions for signing in, creating users, and signing out. Add them to the useFirebaseAuth function and update the default values in your context file. Create a sign-up page, login page, and sign-out button using your useAuth hook.


import firebase from 'firebase/app';
import 'firebase/auth';

const useFirebaseAuth = () => {
  //...

  const signUp = async (email, password) => {
    try {
      await auth.createUserWithEmailAndPassword(email, password);
    } catch (error) {
      console.error(error);
    }
  };

  const signIn = async (email, password) => {
    try {
      await auth.signInWithEmailAndPassword(email, password);
    } catch (error) {
      console.error(error);
    }
  };

  const signOut = async () => {
    try {
      await auth.signOut();
    } catch (error) {
      console.error(error);
    }
  };

  return { authUser, loading, signUp, signIn, signOut };
};

Leave a Reply