Back
Mobile | Mon Jun 27 2022

Sign In with Google

Transcribed by Alvaro Peña.

Welcome! 🎉

This guide will assist you in integrating Google Sign-In for Web, iOS, and Android platforms.

Download the resources for this project from this GitHub repository.

Interested in integrating Google and Facebook? Explore this project!

To start, create a new expo application using the following command:

npx create-expo-app tutorial-google

Dependencies

You'll need to install the following dependencies:

npx expo install expo-auth-session expo-crypto expo-web-browser
  • We install expo-web-browser to provide in-app browsing capabilities, enabling Google Sign-In without leaving the app.
  • We also need react-native-web because we're demonstrating its compatibility with the web platform.
  • @expo/webpack-config is required for building the web application.
  • Finally, the optional @react-native-async-storage/async-storage package allows us to store user information after sign-in, so they won't need to sign in every time they use the app.

Google Cloud

You'll need to create a new project in Google Cloud. Please name it tutorial. Then navigate to Navigation menu > API & Services > Credentials > Create credentials > OAuth Client ID > Configure consent screen.

Set User Type to External, name your app, and add developer and contact emails. Leave Scopes as default. Optionally, you can add test users. Then, return to the dashboard.

Credentials

Web application

To create credentials:

  1. Navigate to Create credentials > OAuth Client ID > Web application.
  2. Run the following command on the terminal to start your application:
npx expo start —web —htpps
  1. Add http://localhost:19006 to both Authorized Javascript Origins and Redirect URLs.

If your application is deployed, provide your domain and the link to your web application.

Remember to securely store your Client ID. Do not share it with anyone!

iOS

To get the credentials for iOS:

  1. Navigate to Create credentials > OAuth Client ID > iOS.
  2. We need a Bundle ID for iOS. Run the following command on the terminal to get it:
npx expo prebuild
  1. Paste the Bundle Identifier in Bundle ID and then click Create.
  2. Securely store the Client ID for iOS.

Android

To get the credentials for Android:

  1. Navigate to Create credentials > OAuth Client ID > Android.
  2. You will need a SHA-1 certificate fingerprint. To get this, run the following command on the terminal:
expo:credentials manager > android > yes > update > Generate new keystore

Copy and paste the SHA-1 for Android. Hit create and then copy the Client ID in App.js

With these steps done, we can start to implement the code for the application.

App.js

import { useEffect, useState } from "react";
import { StyleSheet, Text, View, Button, Image } from "react-native";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
import AsyncStorage from "@react-native-async-storage/async-storage";
 
WebBrowser.maybeCompleteAuthSession();
 
export default function App() {
  const [token, setToken] = useState("");
  const [userInfo, setUserInfo] = useState(null);
 
  const [request, response, promptAsync] = Google.useAuthRequest({
    androidClientId: "",
    iosClientId: "",
    webClientId: "",
  });
 
  useEffect(() => {
    handleEffect();
  }, [response, token]);
 
  async function handleEffect() {
    const user = await getLocalUser();
    console.log("user", user);
    if (!user) {
      if (response?.type === "success") {
        // setToken(response.authentication.accessToken);
        getUserInfo(response.authentication.accessToken);
      }
    } else {
      setUserInfo(user);
      console.log("loaded locally");
    }
  }
 
  const getLocalUser = async () => {
    const data = await AsyncStorage.getItem("@user");
    if (!data) return null;
    return JSON.parse(data);
  };
 
  const getUserInfo = async (token) => {
    if (!token) return;
    try {
      const response = await fetch(
        "https://www.googleapis.com/userinfo/v2/me",
        {
          headers: { Authorization: `Bearer ${token}` },
        }
      );
 
      const user = await response.json();
      await AsyncStorage.setItem("@user", JSON.stringify(user));
      setUserInfo(user);
    } catch (error) {
      // Add your own error handler here
    }
  };
 
  return (
    <View style={styles.container}>
      {!userInfo ? (
        <Button
          title="Sign in with Google"
          disabled={!request}
          onPress={() => {
            promptAsync();
          }}
        />
      ) : (
        <View style={styles.card}>
          {userInfo?.picture && (
            <Image source={{ uri: userInfo?.picture }} style={styles.image} />
          )}
          <Text style={styles.text}>Email: {userInfo.email}</Text>
          <Text style={styles.text}>
            Verified: {userInfo.verified_email ? "yes" : "no"}
          </Text>
          <Text style={styles.text}>Name: {userInfo.name}</Text>
          {/* <Text style={styles.text}>{JSON.stringify(userInfo, null, 2)}</Text> */}
        </View>
      )}
      <Button
        title="remove local store"
        onPress={async () => await AsyncStorage.removeItem("@user")}
      />
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  text: {
    fontSize: 20,
    fontWeight: "bold",
  },
  card: {
    borderWidth: 1,
    borderRadius: 15,
    padding: 15,
  },
  image: {
    width: 100,
    height: 100,
    borderRadius: 50,
  },
});

app.json

{
  "expo": {
    "name": "google-sign-in",
    "slug": "google-sign-in",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "light",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.betomoedano.googlesignin"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.betomoedano.googlesignin"
    },
    "web": {
      "favicon": "./assets/favicon.png"
    },
    "scheme": "myGoogleApp"
  }
}

Conclusion

Using Google Sign In provides a better user experience although we need to configure a few extra steps.

Youtube GitHubDownload

Go back to Projects