Login with Google is a convenient way to allow users to register and authenticate into your React Native app. It reduces friction in the onboarding flow, and therefore it maximizes user growth. Firebase provides a seamless experience of adding Google Login into any React Native app with almost no effort. In this React Native tutorial, we are going to implement Login with Google in React Native with Firebase.

react native google login

Not only a social provider can act as a single source of authentication between your users and your app, but it also eliminates the need to implement extra functionalities that can bring a lot of hassle. Some of these functionalities can be email verification, forgot password, reset password, one click email, and so on.

In this tutorial, by using a package provided by React Native community and by leveraging Firebase to access auth credentials, let us learn how you can add Google sign-in provider method in your React Native apps.

1. Installing dependencies

Start by creating a new React Native project. Do note that this tutorial uses a react-native version above 0.60.x. If you are using a version below that, make sure to seek guidance on how to link native binaries for the libraries mentioned in this tutorial.

Open up a terminal window, and generate a new React Native project as follows:

npx react-native init rnGoogleSignIn

# navigate inside the directory
cd rnGoogleSignIn

Now, install the package @react-native-community/google-signin:

yarn add @react-native-community/google-signin

Since I’ll use the iOS simulator to test the demo app in this tutorial, I am going to discuss the iOS configuration part in details.

A word of caution: Android developers please note that you are going to follow the guide from here on how to configure this library to React Native app.

2. Create a new Firebase Project

Right now, you are going to need a Firebase project for two reasons:

  • Creating a Google Project
  • Access to WEB_CLIENT_ID and REVERSE_CLIENT_ID of a Google Project

For that, go to Firebase console and create a new project.

in1

Complete the details of your Firebase project.

in2

Click the button Create project and you’ll be redirected to the dashboard screen. On the left side menu, click the settings icon, and then go to Project Settings.

in3

From there, click on the Add app button, select the appropriate platform, and follow the included instructions. Select the appropriate platform depending on the mobile OS. For example, for this tutorial, I am going to select iOS.

in4

Then, enter the details regarding the bundle name. After that, in step 2 download the file GoogleService-info.plist if your selected platform in the previous step is iOS.

in5

For Android devs, you will download google-services.json and save it at the location android/app/.

3. Enable Google Sign in from Firebase

From the side menu, go to the Authentication tab and then select Sign-in methods. You are going to be welcomed by all the providers that a Firebase project supports for any type of platforms such as web or mobile.

Enable the Google Sign-in method.

react native firebase google login

Make sure you save the web client id inside your React Native project in a file utils/keys.js:

export const WEB_CLIENT_ID = 'YOU_WEB_CLIENT_ID'

4. Configure Google-Signin library

To begin, open the file ios/Podfile and add the following line. This is going to install the Google Signin SDK using Cocoapods.

pod 'GoogleSignIn', '~> 5.0.2'

Open a terminal window to install the pods:

cd ios/

pod install

# after pods install
cd..

Open the ios/rnGoogleSignIn.xcworkspace inside Xcode. Go to Build phases panel and under it open a section Link binary with libraries to make sure libRNGoogleSignin.a exists.

ios firebase react native

Also, under Copy Bundle Resources, make sure GoogleService-Info.plist exists. If not, manually add it.

in8

Then, open the Info panel and go to the section URL Types.

google login react native

Add REVERSE_CLIENT_ID (which can be found in file GoogleService-Info.plist) as the value of the field URL Schemes.

react native firebase google signin

That’s it. You can now start working on the app.

5. Build a Login Screen Component

Create a new file screens/Login.js in your React Native project. Start by importing the following statements.

import React, { useState, useEffect } from 'react'
import {
  View,
  Text,
  StatusBar,
  Image,
  StyleSheet,
  Button,
  Alert
} from 'react-native'
import {
  GoogleSigninButton,
  GoogleSignin,
  statusCodes
} from '@react-native-community/google-signin'
import { WEB_CLIENT_ID } from '../utils/keys'

In the above snippet, WEB_CLIENT_ID is what you saved from Firebase Google Sign in the panel, earlier in this tutorial.

The google-signin library also provides some ready to use helper functions as well as a visual component to be rendered directly within the app. One is called GoogleSigninButton. This button component can be customized to your needs.

GoogleSignin contains the API functionalities that are going to be used to sign in, and sign out. The statusCodes import is essential in determining what type of error has occurred during the process of sign in.

Next, let us define three state variables using React.useState() hook to keep track of

  • userInfo for the user information after a successful login. Initially, it going to be null.
  • isLoggedIn to check whether the user is logged in or not. Initially, it going to be false.
  • error that is going to be for statusCodes. Initially, it going to be null.
{
  idToken: string,
  serverAuthCode: string,
  scopes: Array<string>, // on iOS this array is empty if no additional scopes are defined
  user: {
    email: string,
    id: string,
    givenName: string,
    familyName: string,
    photo: string, // url
    name: string // full name
  }
}

After a successful sign-in, the process returns a user object (an example shown above) that is going to be stored inside the userInfo state variable.

export default function Login() {
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  const [userInfo, setUserInfo] = useState(null)
  const [error, setError] = useState(null)
}

Create a helper function called configureGoogleSign(). Inside this function, it is essential to configure GoogleSignin options such as webClientId and offlineAccess.

function configureGoogleSign() {
  GoogleSignin.configure({
    webClientId: WEB_CLIENT_ID,
    offlineAccess: false
  })
}

It is also essential to call this helper method before the actual signin method is called. Thus, the method is required to be invoked when the app starts. This is going to be done with the help of React.useEffect().

useEffect(() => {
  configureGoogleSign()
}, [])

Then, define a method called signIn that is going to be an asynchronous function. This method is responsible to prompt a modal to let the user sign in into your React Native application. On success, it also provides a valid userInfo object. On error, there can be different scenarios that are essential to handle using statusCodes as shown below.

async function signIn() {
  try {
    await GoogleSignin.hasPlayServices()
    const userInfo = await GoogleSignin.signIn()
    setUserInfo(userInfo)
    setError(null)
    setIsLoggedIn(true)
  } catch (error) {
    if (error.code === statusCodes.SIGN_IN_CANCELLED) {
      // when user cancels sign in process,
      Alert.alert('Process Cancelled')
    } else if (error.code === statusCodes.IN_PROGRESS) {
      // when in progress already
      Alert.alert('Process in progress')
    } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
      // when play services not available
      Alert.alert('Play services are not available')
    } else {
      // some other error
      Alert.alert('Something else went wrong... ', error.toString())
      setError(error)
    }
  }
}

For example, when a status code from the above snippet renders due to an error, it is going to be displayed in an alert box like below:

in13

Next, create another asynchronously invoked helper method called getCurrentUserInfo(). This method is going to return the current user.

async function getCurrentUserInfo() {
  try {
    const userInfo = await GoogleSignin.signInSilently()
    setUserInfo(userInfo)
  } catch (error) {
    if (error.code === statusCodes.SIGN_IN_REQUIRED) {
      // when user hasn't signed in yet
      Alert.alert('Please Sign in')
      setIsLoggedIn(false)
    } else {
      Alert.alert('Something else went wrong... ', error.toString())
      setIsLoggedIn(false)
    }
  }
}

The last asynchronous method your app needs is called signOut(). This is going to sign out the user from the app.

async function signOut() {
  try {
    await GoogleSignin.revokeAccess()
    await GoogleSignin.signOut()
    setIsLoggedIn(false)
  } catch (error) {
    Alert.alert('Something else went wrong... ', error.toString())
  }
}

6. Add Google Sign In Button

To continue directly from the previous section, add the following return statement to the Login screen component. This is going to display a Sign In button.

export default function Login() {
  // ...

  return (
    <>
      <StatusBar barStyle='dark-content' />

      <View style={styles.container}>
        <GoogleSigninButton
          style={styles.signInButton}
          size={GoogleSigninButton.Size.Wide}
          color={GoogleSigninButton.Color.Dark}
          onPress={() => signIn()}
        />
      </View>
    </>
  )
}

The corresponding styles of the above snippet are defined as:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  signInButton: {
    width: 192,
    height: 48
  }
})

Now, build the app using the correct OS platform from a terminal window:

npx react-native run-ios

# or

npx react-native run-android

This is going to provide you the following output:

login with google

7. Check the user’s login state

In this section, let us display the Login screen to display a message whether a user is logged in or not after the Sign-in button gets pressed.

<View style={styles.statusContainer}>
  {isLoggedIn === false ? (
    <Text style={styles.message}>You must sign in!</Text>
  ) : (
    <Button onPress={() => signOut()} title='Sign out' color='#332211' />
  )}
</View>

If the user is logged in, we are going to display a sign out button that you will see shortly. Here are the corresponding styles for above code snippet:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  signInButton: {
    width: 192,
    height: 48
  }
  statusContainer: {
    marginVertical: 20
  },
  message: {
    fontSize: 20,
    color: 'red'
  }
})

Here is the output after this step:

in12

8. Display the user information

The final piece of the puzzle is to display the user information when they successfully log in.

Here is the complete code snippet of what is being rendered on the Login screen. Using the userInfo object, the value of the user’s name or profile image is being obtained.

return (
  <>
    <StatusBar barStyle='dark-content' />
    <View style={styles.container}>
      <GoogleSigninButton
        style={styles.signInButton}
        size={GoogleSigninButton.Size.Wide}
        color={GoogleSigninButton.Color.Dark}
        onPress={() => signIn()}
      />
      <View style={styles.statusContainer}>
        {isLoggedIn === false ? (
          <Text style={styles.message}>You must sign in!</Text>
        ) : (
          <Button onPress={() => signOut()} title='Sign out' color='#332211' />
        )}
      </View>
      <View style={styles.userInfoContainer}>
        {isLoggedIn === true ? (
          <>
            <Text style={styles.displayTitle}>
              Welcome {userInfo.user.name}
            </Text>
            <View style={styles.profileImageContainer}>
              <Image
                style={styles.profileImage}
                source={{
                  uri: userInfo && userInfo.user && userInfo.user.photo
                }}
              />
            </View>
          </>
        ) : null}
      </View>
    </View>
  </>
)

Also, here are the complete styles:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  signInButton: {
    width: 192,
    height: 48
  },
  statusContainer: {
    marginVertical: 20
  },
  message: {
    fontSize: 20,
    color: 'red'
  },
  userInfoContainer: {
    marginVertical: 20
  },
  profileImageContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
    flexDirection: 'row',
    justifyContent: 'center'
  },
  profileImage: {
    width: 100,
    height: 100
  },
  displayTitle: {
    fontSize: 22,
    color: '#010101'
  }
})

Here is the final demo so far. When the app renders for the first time and the user clicks on the sign-in button.

in14

A modal appears for the user to enter their Google account credentials.

in15

On successful sign in:

in16If the app is closed or the user has already logged in for the first time, the helper method getCurrentUserInfo() is triggered to avoid the user to enter their credentials again and again. This method is called Silent Login and is provided by GoogleSignin.signInSilently().

in17

That’s it. You have just learned how to implement a Google Sign in a React Native app using Firebase. In the next section, let us extend our journey a bit.

9. Integrating Firebase SDK

Since you are already using Firebase, let’s store the instance of the user’s login information. In real-time mobile apps, this is a helpful feature since Firebase provides you a backend system without setting it up one. Usually, a mobile app is going to store user’s data or behavior in relation to the app on a custom backend or a provider like Firebase.

To begin connecting Firebase SDK with this React Native app, open up the terminal window and start by installing the latest version (the version 6 at the time of writing this tutorial) of react-native-firebase.

yarn add @react-native-firebase/app

If you have used react-native-firebase version 5 or below, you must have noticed that it was a monorepo that used to manage all Firebase dependencies from one module.

Version 6 brings you to only install those Firebase dependencies based on features that you want to use. For example, in the current app, you are going to start by adding the auth package. Also, do note that the core module: @react-native-firebase/app is always required.

10. Adding Firebase credentials to an iOS app

Since you have already gone through the process of creating a GoogleService-Info.plist file, let us complete the remaining steps.

Open ios/rnGoogleSignIn/AppDelegate.m file and add the following header.

#import <Firebase.h>

Within the didFinishLaunchingWithOptions method, add the following configure method:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    if ([FIRApp defaultApp] == nil) {
      [FIRApp configure];
    }

Open a terminal window to install pods.

cd ios/ && pod install

# after pods are installed
cd ..

11. Installing Firebase auth package

To support Google Sign in from Firebase, open a terminal window to install the auth package.

yarn add @react-native-firebase/auth

# Using iOS
cd ios/ && pod install

# After installing
cd ..

12. Store user credentials in Firebase backend

The react-native-firebase package requires you to use @react-native-community/google-signin package since the latter provides access to a user’s accessToken and idToken. Both of these values are necessary to create a Firebase credential.

Start by importing the following statement inside the Login.js screen component.

// ... after other import statements
import { firebase } from '@react-native-firebase/auth'

All you have to do is modify the asynchronous signIn() helper method. Add the following code snippet in the try block to create a new firebase credential with tokens as well as save the credential to the firebase backend using auth().signInWithCredential().

// create a new firebase credential with the token
const { accessToken, idToken } = await GoogleSignin.signIn()
const credential = firebase.auth.GoogleAuthProvider.credential(
  idToken,
  accessToken
)

// login with credential
await firebase.auth().signInWithCredential(credential)

That’s it. Now, when a user logs in through the app, their credential is going to be saved as shown below.

in18

Conclusion

Thanks for going through the whole tutorial. I am sure you must have learned the key points here. Let me summarize it again for you. In this tutorial, you learned:

  • How to integrate and use Google Sign-in provider
  • Access user’s details from their Google account
  • Use @react-native-community/google-signin package
  • Integrating react-native-firebase version package in a react native app
  • Store user credentials in Firebase backend

That’s how you add a Login with Google feature to any React Native app. Firebase is a great tool that developers can leverage in order to build serverless cross-platform mobile apps really quickly.

If you run into any issues while adding Google Login into your React Native apps, please let us know in the comments. Also, if you’ve enjoyed this tutorial, please consider following us on Twitter to get notified of more tutorials and starter kits.


Leave a Reply

Your email address will not be published. Required fields are marked *

Shopping Cart