React-Firebase auth

What is authentication ?

Authentication is the means of verifying that a person is who they claim to be based on 3 things :

  1. Something they know (eg : a password)
  2. Something they have (eg : a key)
  3. Something they are (eg : fingerprint)

Integrating authentication with frontend applications can be quite cumbersome and verbose using conventional methods like JSON Web Tokens as all the logic handling for encrypting and decrypting has to be written by the developer

This is where Google Firebase's Authentication comes as a relief, helping the developer setup authentication using not just custom email and password, but even Single Sign On features with over 15 options including Facebook, GitHub, Apple etc,

Ok, but what does Single Sign On (SSO) Mean ?

SSO is the ability to sign into a third party website instead of creating a new login account specifically for that website.

Let's get started now !

All the code for this project can be accessed from here

This project is consisting of 2 main parts :

  1. Creating a React Context for authentication and its related functions like sign-up, login, forgot-password etc.
  2. Using this context to secure the routes we wish to

Run these commands to install the necessary packages

npx create-react-app reactfire-auth
npm i firebase react-router-dom

Creating the authentication context

First, we setup firebase in our project :

Create an account on Google Firebase and create a project (it's completely FREE).

Then, just add an application to this project and get all the connection info about this project

This is simply involving just exporting the necessary stuff out of Firebase API in one file to handle all Firebase API related stuff, to be used in components and logic elsewhere.

import firebase from "firebase/app"
import "firebase/auth"

const app = firebase.initializeApp({
  apiKey: ,
  authDomain:,
  databaseURL: ,
  projectId: ,
  storageBucket: ,
  messagingSenderId: ,
  appId: 
})

export const auth = app.auth()
export default app

Next, we write the context code keeping these things in mind :

Requirement Solution Implementation
Authenticate and store user object somewhere Manage the state of the currently signed in user useState to store this user's info
Secure multiple components and routes with this auth info Share this user's auth info with everyone Context API to share it with all components
Reverify if users sign out or do something else that changes their auth info Reauthenticate each time the user's auth state changes useEffect will be used
Too cumbersome to setup a context in every component Create a custom hook to fetch user auth info from context useContext will be used
import React, { useContext, useState, useEffect } from "react"
import { auth } from "../firebase"

const AuthContext = React.createContext()

export function useAuth() {
  return useContext(AuthContext)
}

export function AuthProvider({ children }) {
  const [currentUser, setCurrentUser] = useState()
  const [loading, setLoading] = useState(true)

  function signup(email, password) {
    return auth.createUserWithEmailAndPassword(email, password)
  }

  function login(email, password) {
    return auth.signInWithEmailAndPassword(email, password)
  }

  function logout() {
    return auth.signOut()
  }

  function resetPassword(email) {
    return auth.sendPasswordResetEmail(email)
  }

  function updateEmail(email) {
    return currentUser.updateEmail(email)
  }

  function updatePassword(password) {
    return currentUser.updatePassword(password)
  }

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged(user => {
      setCurrentUser(user)
      setLoading(false)
    })

    return unsubscribe
  }, [])

  const value = {
    currentUser,
    login,
    signup,
    logout,
    resetPassword,
    updateEmail,
    updatePassword
  }

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  )
}

Thus, we have done 5 things here :

  1. Setup a state called user to store all the currently signed in information about the user
  2. Setup functions that can be called to implement authentication features by interacting with Firebase's API. These functions help us setup :
    1. Sign up
    2. Login
    3. Logout
    4. Forgot Password
    5. Update Email
    6. Update Password
  3. Next, we shared all this function and information with all app level components by setting up a Provider, a custom hook and React's context API.
  4. Also,we have setup reauthentication to take place each time the users do something that change their authentication information like updating email ID, changing password etc.

Now, we can setup Private Routes to safeguard certain routes on our frontend app

Private Routes

import React from "react"
import { Route, Redirect } from "react-router-dom"
import { useAuth } from "../contexts/AuthContext"

export default function PrivateRoute({ component: Component, ...rest }) {
  const { currentUser } = useAuth()

  return (
    <Route
      {...rest}
      render={props => {
        return currentUser ? <Component {...props} /> : <Redirect to="/login" />
      }}
    ></Route>
  )
}
Private Route setup as a separate component to reuse it in several routes containing several components and pages
import React from "react"
import { AuthProvider } from "../contexts/AuthContext"
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
import Dashboard from "./Dashboard"

function App() {
  return (
      <div className="w-100" style={{ maxWidth: "400px" }}>
        <Router>
          <AuthProvider>
            <Switch>
              <PrivateRoute exact path="/" component={Dashboard} />
            </Switch>
          </AuthProvider>
        </Router>
      </div>
  )
}

export default App
The main App.js file is given the Provider and the PrivateRoute component to establish authentication logic accross the entire app

Thus, by simple implementation of features from React Router, we have simply just inherited the shared information (on current user's authentication) from our context by using our custom hook, and setup redirection in case the information is faulty

Conclusion

This is how we can easily integrate authentication into our frontend React app using Firebase auth.

If you're more interested in this, I would highly recommend you to explore the Authorization and Role Based Access Control features that Firebase has to offer.

Also, check out this amazing YouTube tutorials to learn more about this !!

React Authentication Crash Course With Firebase And Routing
🚨 IMPORTANT:Learn React Today Course: https://courses.webdevsimplified.com/learn-react-todayAuthentication is crucial for nearly every application. It can a...
Firebase Auth Tutorial
Share your videos with friends, family, and the world