Sign-in with Google With React and Firebase

Recently, I was trying to integrate Sign-In with Google in my React application using Firebase. This post describes how I achieved it.

Things you need?

Workflow (Demo)

The app has 2 pages:

  • Login (which is the default page users lands on)
  • Home page which has restricted access and only users who have authenticated themselves with Google would be able to view it

When a user lands on the main page (http://localhost:3000), they see a following page

Sign In Page

When user clicks on “Sign In With Google”, the workflow kicks in and takes them to following page

Firebase Auth Redirection from React App

When a User authenticate with Google, the app takes them back to the page where they see Splash screen (or Loading screen)

Firebase Authentication completed. Redirected back to React App.

And few moments later, when the user is captured by Firebase, the Home page appears as

Authenticated users see their Home Page

When clicked on Sign out, the user is taken back to the Login Page.

How does this work?

Sign In with Google Workflow with Firebase Authentication

First of all, in index.js you set up routing as

<Router history={customHistory}>
<div>
<Route path="/login" component={Login}/>
<Route path="/app/home" component={Home}/>
<Redirect from="/" to="/login"/>
</div>
</Router>

Next, when user click on “Sign In with Google”, we do 2 things

  • Set up a token in localStorage to indicate the Firebase Authentication Workflow is in progress
  • Call the firebase authentication workflow. In Login.js do
handleGoogleLogin() {
loginWithGoogle()
.catch(function (error) {
alert(error); // or show toast
localStorage.removeItem(firebaseAuthKey);
});
localStorage.setItem(firebaseAuthKey, "1");
}

The workflow is then handled by firebase and once the user is authenticated, firebase callbacks the react app. In Login.js, we check that as

firebaseAuth().onAuthStateChanged(user => {
if (user) {
console.log("User signed in: ", JSON.stringify(user));

localStorage.removeItem(firebaseAuthKey);

// here you could authenticate with you web server to get the
// application specific token so that you do not have to
// authenticate with firebase every time a user logs in
localStorage.setItem(appTokenKey, user.uid);

// store the token
this.props.history.push("/app/home")
}
});

As you could see that we are setting appTokenKey here as user id from Firebase. At this moment, you could call your API server to generate a token that could be saved in localStorage.

The appTokenKey used in further communication with your Api Server and there is no further need to authenticate with Firebase every time until user logs out. Now, when the next time user comes to the app and if appTokenKey is present in localStorage, your app bypasses the authentication with Firebase because a valid token is available to interact with Api Server.

We remove the key to that we set in earlier step to indicate that Firebase Authentication is now complete. The purpose of using that variable in localStorage is when the Firebase calls back the application, it shows the Login Page by default. With the variable in localStorage we could now show a Splash screen to user, by the time actual user object is sent back by Firebase. In render() function, we could see

render() {
if (localStorage.getItem(firebaseAuthKey) === "1") return <SplashScreen />;
return <LoginPage handleGoogleLogin={this.handleGoogleLogin}/>;
}

When user clicks on “Sign Out”, we do 2 things

  • Signs out the user from firebase
  • Remove the appToken key that was saved in localStorage to communicate with API Server. This would make sure that the next time user comes to your app, the see the Login Page

The codebase for this demo is available at https://github.com/hhimanshu/react-firebase-social-authentication

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.