Overview
Firebase is a great provider for hooking up easy and simple authentication to a new or existing project, and can easily be integrated with other features of Google Cloud Platform. Adding it to your application can be simple, but a lot of tutorials don't cater for larger scale applications, and how it could be implemented cleanly and with quality assurance in mind.
Assumed Knowledge
- Firebase
- Typescript
- React
- React Hooks (specifically useContext)
Setting Up
GCP and Firebase
To start, you'll need to setup a GCP account and login to the Firebase console at https://console.firebase.google.com/. You'll then need to setup a project for us to use in this run through. For this walkthrough, I've named my project "HooksAuth"
I'm then going to enable email/password and Google Authentication by navigating to the "Authentication" page from the left menu and enabling them there
React
To setup your react project from scratch, you can use create-react-app by running the following command in your cli: npx create-react-app hooksAuth --template typescript
The next (optional) step is to remove all the boilerpate content from your React App. e.g. react images, manifest, App.tsx content etc. This helps me to start from a cleaner slate and not have create-react-app content in my site
Setting up the hooks
We are going to abstract our firebase app away through useContext so it's state can be shared through the app, and any abstractions and access can easily be updated and refactored.
- Create
FirebaseContext.ts
- Add your config to this file (this can be retrieved by registering a web app in the firebase console), and will look something like:
import firebase from 'firebase';
const firebaseConfig = {
apiKey: "KEY",
authDomain: "somedomain.firebaseapp.com",
databaseURL: "https://somedomain.firebaseio.com",
projectId: "hooksauth-ID_HERE",
storageBucket: "hooksauth-ID_HERE.appspot.com",
messagingSenderId: "SENDER_ID",
appId: "APP_ID"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
- Now we want to secure these values using .env (before we accidentally commit anything). To do this, create a file called .env.local in the root of the project, and add this file to .gitignore. In that file, you'll want to define your ID's in something similar to this format:
REACT_APP_API_KEY=KEY
REACT_APP_AUTH_DOMAIN=somedomain.firebaseapp.com
REACT_APP_DB_URL=https://somedomain.firebaseio.com
REACT_APP_PROJECT_ID=hooksauth-ID_HERE
REACT_APP_STORAGE_BUCKET=hooksauth-ID_HERE.appspot.com
REACT_APP_MESSAGING_SENDER_ID=SENDER_ID
REACT_APP_APP_ID=APP_ID
and update your config to be:
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_DB_URL,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_APP_ID,
};
- Move the firebase initialisation. To stop the firebase initialisation happening multiple times, we want to wrap it in an if statement to make it look like:
// Initialize Firebase
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
firebase.analytics();
}
- Now we want to actually do some React stuff. We want to create a context for us to use in the rest of our app. So using react hooks, we will create a context that contains the auth providers we will use, and a way to access our firebase object:
export interface IFirebaseContext {
firebase: firebase.app.App,
authProviders: string[]
}
export const FirebaseContext = React.createContext({} as IFirebaseContext)
And then our provider to wrap the app:
export const FirebaseProvider = ({ children }: any) => {
return (
<div>
<FirebaseContext.Provider value={{ 'firebase': firebase.app(), authProviders } as IFirebaseContext}>
{children}
</FirebaseContext.Provider>
</div>
);
}
- Now to wrap the rest of our app. So in App.tsx, we want to wrap the root div in
<FirebaseProvider>
. And now in the rest of our App, if we want to access our auth object, we would simply callconst firebaseContext = useContext(FirebaseContext);
and access it there. This can be combined with the firebase-ui package to get your authentication up and running in no time
For an example of usage with the react-firebaseui package and saving user data see my github repo: https://github.com/bmpickford/firebase-auth-example
Open to any improvements so feel free to submit a PR or an issue
Top comments (4)
Nice article, thank u
Thanks for the feedback :) I'll try to get around to putting up an example this week sometime!
This is a really awesome starter! Would be good to see an example of using the provider tho.
Thanks for sharing this. Could you provide a sandbox or something ?