Adding Firebase Authentication to React App

Jumanah Al Asadi
8 min readNov 14, 2021

--

Using the latest version of Firebase SDK. 9+. Using React.js create react app. Showing examples of login, sign up, logout, check currentUser.

Start by creating a free, google account. Then open the following link to create a new Google Firebase project. The account will be under Google’s Spark plan which is 100% free.

Click get started. https://firebase.google.com/. Follow the steps. You need to be signed in to your google account. This project will be created under your google account (gmail).

Firebase Set Up

After you are done going through the wizard to create a new project. You will need to add “Firebase authentication” in this project. Since Firebase has a ton of other features in addition to authentication, you can add a Database, Cloud Storage, etc. But for now, only add the Authentication.

When going through this next wizard, I chose the basic email and password option, but you can add any other form of sign in, like sign in with Facebook or Google.. These will not be covered in this tutorial.

Then you must create a link to your react app from Firebase. By doing this, it will create new credentials and a configuration for you to paste in your React app so you can access this specific instance of Firebase from your react app.

To accomplish this, open your project settings, and click add a web app, the </> icon and fill out the instructions, like choosing a name and analytics.

The end result will be credentials for your react app.

Copy paste this entire blob of code to your react app. Of course you should put all secret data in their environment variables, but for now, let’s just pretend we did that.

  • Create an .env file
  • Create variables for all the items, REACT_APP_API_KEY ..etc and so on
  • Refer to them as process.env.REACT_APP_API_KEY

Before copying this code, we should install firebase (the newest version). This way we can initialize Firebase in our React app.

npm install firebase

We can copy all this code from the previous step, supplied to us from the end of the wizard.

Inside of index.js, just above the ReactDOM.render statement, there we can call the initializeApp function with the credentials we have. Don’t forget to put this data instead in .env file and never push them to Github or Bitbucket.

Now we are ready to use our Firebase instance. The configuration is all set up :-)

Log in + Sign Up + Log Out examples

*Don’t forget to install the Firebase SDK into your project. Alright let’s do this :)

We can start by creating a login, and sign up page in our application. Add them using react-router-dom and create components for them. Add the following routes.

  • /login
  • /signup

In these pages, we can build a form, that will call the functions to authenticate into Firebase.

We will import them when necessary:

import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut
} from "firebase/auth";

Let’s start with the LoginPage component:

A simple form, with no validation, just to illustrate the integration of Firebase. We store the username and password in the state variables. On Submit, we call a function called loginUser that I created.

     <form onSubmit={loginUser}>
<label htmlFor="user"> Email </label>
<input
onChange={(event) => {
setUsername(event.target.value);
}}
name="user"
required
/>
<label htmlFor="password"> Password </label>
<input
onChange={(event) => {
setPassword(event.target.value);
}}
name="password"
type="password"
required
/>
<input name="login" type="submit" value="login" />
</form>

The loginUser function can look like this. It will call the signInWithEmailAndPassword method from Firebase Auth. We pass it the username and password.

import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
} from "firebase/auth";
import { useState } from "react";
export const LoginPage = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const loginUser = async(event) => {

event.preventDefault();
const auth = getAuth();
try {
const user = await signInWithEmailAndPassword(auth, username, password);
console.log ("User logged in", user);
history.push('/');
} catch (error) {
const errorCode = error.code;
console.log ("Error", errorCode);
}
};

If this works, you can store the current user in a global state, if you like. Otherwise you can redirect the user into the secured part of your application.

This will display an error if the user doesn’t exist. Which is why we will build the sign up functionality next.

Let’s create the SignUpPage component:

A simple form, with no validation, just to illustrate the integration of Firebase. We store the username and password in the state variables. On Submit, we call a function called signUpUser, a function I have created.

      <form onSubmit={signUpUser}>
<label htmlFor="user"> Email </label>
<input
onChange={(event) => {
setUsername(event.target.value);
}}
name="user"
required
/>
<label htmlFor="password"> Password </label>
<input
onChange={(event) => {
setPassword(event.target.value);
}}
name="password"
type="password"
required
/>
<input name="submit" type="submit" value="sign up" />
</form>

Sign up user, will look like this. It will call the createUserWithEmailAndPassword method from Firebase Auth. We pass it the username and password. It will return the new user, it creates.

import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
} from "firebase/auth";
import { useState } from "react";
export const SignInPage = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const signUpUser = async (event) => {
event.preventDefault();
const auth = getAuth();
try {
const user = await createUserWithEmailAndPassword(auth, username, password);
console.log ("New user created", user);
} catch (error) {
const errorCode = error.code;
console.log ("Error", errorCode);
}
};

At this point we may auto log the user in, and route the user to the home page, or alternatively we can route them to the login page, where they must login with their new account.

Let’s create the Logout component:

In the case that you need to logout a user from Firebase, you can make a log out component, which calls the the logout method. You can put this component in your navigation.

Anywhere else you need to logout the user, you can call the signOut function from firebase.

This will clear the current user logged in from the Firebase instance.

import { getAuth, signOut, onAuthStateChanged } from "firebase/auth";
import { useEffect, useState } from "react";
import { useHistory } from 'react-router-dom';
import './styles.css'
export const Logout = () => {
const history = useHistory();
const [user, setUser] = useState(null);
useEffect(
() => {
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
setUser(auth.currentUser)
} else {
setUser(null)
}
});

}, []
)
const logoutUser = async () => {
const auth = getAuth();
try {
await signOut(auth);
history.push('/login')
} catch (error) {
console.log (error)
}
}
return (
user && <button className="logout-btn" onClick={logoutUser}> Logout </button>
)
}

After doing so, we may push the user back to the login screen. We should also clear any local storage or global state we have, and set our app’s current user to null, if we have one.

Check if a user is logged in + Protecting a page from unauthenticated users

Getting current user

To check if a user is logged in we can always get that information from getAuth. An example on a page is:

We can also push them to the login page, if we see that there is no current user present in the firebase instance.

If there is a current user, the way to clear this is by calling the Firebase signOut method. Otherwise, we may simply grab the access token, email, and other info about the user from the getAuth() method, ex. if we wish to greet the user by their display name, or photo.

import { getAuth, signOut, onAuthStateChanged } from "firebase/auth";import { useEffect, useState } from "react";
import { useHistory } from 'react-router-dom';
import './styles.css'export const HomePage = () => {const history = useHistory();
const [user, setUser] = useState(null);

useEffect(
() => {
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
setUser(auth.currentUser)
} else {
setUser(null);
history.push('/login');
}
});

}, []
)
}, []);

We can also grab the token from here incase we wish to send it with requests to a secured API.

Here is an example of the data you can get:

At any time, you may view your signed up users in the Firebase console:

  • You can see when they last logged in
  • Their sign up method
  • Their user id

Next steps

  • You can protect your React app by storing the logged in user, in a user — context or redux (global state), and check if there is no logged in user, you can boot the unauthenticated user from your application, and route them to the login page
  • Create a fancy sign up page, or integrate the Firebase pre-built UI, so you don’t have to make your own sign up and login components from scratch.
  • Add / allow other sign in methods (google, facebook, etc)
  • Support: https://firebase.google.com/docs/auth/web/password-auth

Thanks for reading :-)

--

--

Jumanah Al Asadi

I am just a web developer who loves writing, teaching and music :) My teaching style is playful and fun. At least I hope, lol :p