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 :
- Something they know (eg : a password)
- Something they have (eg : a key)
- 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 :
- Creating a React Context for authentication and its related functions like sign-up, login, forgot-password etc.
- 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 :
- Setup a state called user to store all the currently signed in information about the user
- Setup functions that can be called to implement authentication features by interacting with Firebase's API. These functions help us setup :
- Sign up
- Login
- Logout
- Forgot Password
- Update Email
- Update Password
- 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.
- 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
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 !!