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.
OAuth 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:
- Navigate to Create credentials > OAuth Client ID > Web application.
- Run the following command on the terminal to start your application:
npx expo start —web —htpps
- 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:
- Navigate to Create credentials > OAuth Client ID > iOS.
- We need a Bundle ID for iOS. Run the following command on the terminal to get it:
npx expo prebuild
- Paste the Bundle Identifier in Bundle ID and then click Create.
- Securely store the Client ID for iOS.
Android
To get the credentials for Android:
- Navigate to Create credentials > OAuth Client ID > Android.
- 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.
Links
Go back to Projects