Today we are going to learn how to implement Google Login with Google Sign for React Native and that is also compatible with Expo.

We are going to use the library react-native-google-signin/google-signin
First let’s install the necessary library:
npx expo install @react-native-google-signin/google-signin
Important, for the library to work you must have a native app. (Here I show you how to generate a native development build for Expo)
Now we need to set up our Android folder. If we don’t have it, we do:
npx expo prebuild
As indicated in the official documentation:
Let’s go to Android/build.gradleNow let’s go to build.gradleNow we have the project correctly configured.
Returns only the HTML translated without any addition.
Now we must generate the necessary ids to use the service. We will need an iOS app id and another one for web (the Android authentication uses the web id).
Now, you have to log in to the Google Developer Center (https://cloud.google.com/developers?hl=en-419):

You press on > Start for free and join.
Once inside, click on console.
Inside the console, you have to create a new project. Click on the box that appears at the top left of the title where it says Google Cloud (in my case there is already a project):

Returns only the HTML translated, without any added.

Now we add the name we want and click on create.
Once created, we select our project.
Now click on the navigation menu:

We click on APIs and Services and select Credentials:

We click on Create Credentials and choose OAuth Client ID:

We can create a WEB credential:

Returns the address in JavaScript Origins Authorized

https://auth.expo.io
Now we need to indicate the address of our APP for redirection:
We put our Expo username and the slug field that we have configured in the first step.
https://auth.expo.io/@nombre_usuario_expo/Nombre_app
We click on create:

Returns only the client key and private key.
We have to copy the client key which we will use in the next step.
Generate for iOS:
We are going to create an Oauth client ID but selecting type iOS.

We indicate the type of iOS application, we indicate the name we want to identify our key and in the package ID, we indicate the bundleIdentifier.
In addition, we will have to copy the iOS URI Scheme that indicates us on the right. And we will use it within our file app.json or app.config.js
{ "ios": { "infoPlist": { "CFBundleURLTypes": [ { "CFBundleURLSchemes": ["com.googleusercontent.apps.17898xxxxxx-xxxxxqhqj0exxxxxpl03xxx"] } ] } } }
Now we already have everything configured to start creating the code of React Native.
We are going to create a component called LoginIDS.tsx I will save it inside a folder named util/
Here we have to copy the ids generated in the previous steps:
export const idIos = "XXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com"; export const idWeb = "XXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
We create a component called GoogleAuthentication.tsx (in my case I’m going to use TypeScript)
import React, { useState, useContext } from "react"; import { View} from "react-native"; import { GoogleSignin, GoogleSigninButton, statusCodes, } from '@react-native-google-signin/google-signin'; import { idIos, idWeb } from "@/util/LoginIDS"; GoogleSignin.configure({ webClientId: idWeb, iosClientId: idIos, scopes: ['profile', 'email'], }); const GoogleLogin = async () => { await GoogleSignin.hasPlayServices(); const userInfo = await GoogleSignin.signIn(); return userInfo; }; const GoogleAuthentication: React.FC = () => { //Para login con google: const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const handleGoogleLogin = async () => { setLoading(true); try { await GoogleSignin.hasPlayServices(); const userInfo = await GoogleSignin.signIn(); const { idToken, user } = userInfo; if (idToken) { //console.log('idToken', idToken); obtenerDatosUsuarioGoogle(idToken, user); } //console.log('userInfo', userInfo); } catch (error: any) { console.log('error', error); switch (error.code) { case statusCodes.SIGN_IN_CANCELLED: console.log('SIGN_IN_CANCELLED'); // user cancelled the login flow break; case statusCodes.IN_PROGRESS: console.log('IN_PROGRESS'); // operation (eg. sign in) already in progress break; case statusCodes.PLAY_SERVICES_NOT_AVAILABLE: console.log('PLAY_SERVICES_NOT_AVAILABLE'); // play services not available or outdated break; default: console.log('default'); // some other error happened } } }; async function obtenerDatosUsuarioGoogle(idToken: string, objUser: any) { console.log('userData', JSON.stringify(objUser)); setLoading(false) //AQUI DEBES VALIDAR CON EL SERVIDOR, RECUERDA QUE USA LA FIRMA DE APP WEB }); } return ( <View> <GoogleSigninButton size={GoogleSigninButton.Size.Wide} color={GoogleSigninButton.Color.Dark} onPress={() => { handleGoogleLogin(); }} disabled={loading} /> </View> ) }; export default GoogleAuthentication;
I will now explain the code:
First, I made all the imports from the library and the IDs we created earlier.
GoogleSignin.configure({ webClientId: idWeb, iosClientId: idIos, scopes: ['profile', 'email'], });
Now, I assign the IDs to the library and indicate that I want to get the profile and email (you can specify other scopes).
Only webClientId, iosClientID is indicated, as Android will use webClientId (this is important when you have to validate the token on the server).
Now we already generate the login code, indicating possible errors:
const GoogleLogin = async () => { await GoogleSignin.hasPlayServices(); const userInfo = await GoogleSignin.signIn(); return userInfo; }; const GoogleAuthentication: React.FC = () => { //Para login con google: const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const handleGoogleLogin = async () => { setLoading(true); try { await GoogleSignin.hasPlayServices(); const userInfo = await GoogleSignin.signIn(); const { idToken, user } = userInfo; if (idToken) { //console.log('idToken', idToken); obtenerDatosUsuarioGoogle(idToken, user); } //console.log('userInfo', userInfo); } catch (error: any) { console.log('error', error); switch (error.code) { case statusCodes.SIGN_IN_CANCELLED: console.log('SIGN_IN_CANCELLED'); // user cancelled the login flow break; case statusCodes.IN_PROGRESS: console.log('IN_PROGRESS'); // operation (eg. sign in) already in progress break; case statusCodes.PLAY_SERVICES_NOT_AVAILABLE: console.log('PLAY_SERVICES_NOT_AVAILABLE'); // play services not available or outdated break; default: console.log('default'); // some other error happened } } };
Finally and very importantly, we must validate the generated token with a backend server:
async function obtenerDatosUsuarioGoogle(idToken: string, objUser: any) { console.log('userData', JSON.stringify(objUser)); setLoading(false) //AQUI DEBES VALIDAR CON EL SERVIDOR, RECUERDA QUE USA LA FIRMA DE APP WEB }); }
Here I explain a way to validate the token obtained: https://devcodelight.com/verify-google-auth-google-sign-token-using-python/
If you need to verify the token’s contents, you can use this website: https://jwt.io/
Finally I have added the Google button, you can use your own or the one brought by the library:
<GoogleSigninButton size={GoogleSigninButton.Size.Wide} color={GoogleSigninButton.Color.Dark} onPress={() => { handleGoogleLogin(); }} disabled={loading} />
We will implement a function to log out in this section:
export async function cerrarSesionGoogle() { const hasPreviousSignIn = await GoogleSignin.isSignedIn(); if (hasPreviousSignIn) { await GoogleSignin.signOut(); } }
First check if the session is active and then close it.
We can put this function inside the previously created file <strong>LoginIDS.tsx</strong> and call it from a logout button anywhere in our APP.
await closeGoogleSession();
