A guide on setting up and using Google authentication with AuthSession API in your Expo app.
AuthSession API allows browser-based authentication (using OAuth or OpenID Connect) to your project for Android, iOS, and the web. This guide provides steps on configuring and using the API with Google and a development build.
To use AuthSession API, you'll need to install the following packages in your project:
-
npx expo install expo-auth-session expo-crypto expo-web-browser
If you're using SDK 47 or below, you'll need to install expo-random
instead of expo-crypto
package:
-
npx expo install expo-auth-session expo-random expo-web-browser
expo-random
is deprecated from SDK 48 and above and is replaced by expo-crypto
.
You'll need to provide a Google OAuth client ID to use Google as a login provider. To create a client ID, go to your Google Cloud project's Credentials page. If you don't have an existing project, create a new project.
There are three types of client IDs you can provide to the AuthSession API depending on the type of platform or development phase you are building your project for:
androidClientId
for Android production apps.iosClientId
for iOS production apps.webClientId
for web apps used in the browser.1
On the Credentials page, click the Create credentials button, select OAuth client ID and then click Configure Consent screen. You will be prompted to select properties such as User Type and other app-related information on this page. Continue the process and when you are done, proceed with the next step.
2
For Android, install the expo-application
in your project. It is a peer dependency for expo-auth-session
. Open the terminal window and run the following command:
-
npx expo install expo-application
Create a androidClientId
by following the steps below from the Google Cloud console:
android.package
field, for example, com.example.myapp
.eas credentials -p android
, then select the build profile. For example, if you are generating the credential for development, select the build profile for it.Whenever you change values in the app config file, you'll need to rebuild the native app.
Create a iosClientId
by following the steps below from the Google Cloud console:
ios.bundleIdentifier
field, for example, com.example.myapp
.Whenever you change values in the app config file, you'll need to rebuild the native app.
1
For a development build and when setting up production apps, define scheme
in the app config file. It is required for the authentication flow to complete the process and redirect the user back to the app. It handles the process of deep linking back to the app.
{
"expo": {
"scheme": "yourscheme"
}
}
If you do not provide a value for the scheme
, the authentication flow will complete, however, the user will not be redirected back to the app. They will have to manually exit the authentication popup which will result in the rejection of the process.
2
Add the following import statements to your project code. The WebBrowser
API and the Google
provider from the expo-auth-session
are essential to handle the authentication process.
import * as WebBrowser from 'expo-web-browser';
import * as Google from 'expo-auth-session/providers/google';
3
Expo's WebBrowser API provides maybeCompleteAuthSession()
method to dismiss the popup when the authentication sessions is completed successfully. It uses the redirect URL added in the provider's authorized list of URLs.
Invoke this method to the app screen you want to redirect back to by adding the following code snippet:
WebBrowser.maybeCompleteAuthSession();
If this method is not invoked, the popup will not dismiss itself.
4
Google.useAuthRequest()
hook provides request
and response
objects. It allows for async setup, which means that a mobile web browser won't block the request. It also accepts an object of client IDs that are generated in the Google Cloud console.
Define this hook inside the React component by adding the code snippet below:
const [request, response, promptAsync] = Google.useAuthRequest({
androidClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
iosClientId: 'GOOGLE_GUID.apps.googleusercontent.com',
});
In the above code snippet, replace the GOOGLE_GUID
with the client ID generated in the Google Cloud console for your app. Also, you include the client IDs for the platforms you want to support.
5
useAuthRequest()
hook also provides promptAsync()
that prompts the user to authenticate by opening a web browser. It is invoked when the user clicks the login button. The button must be disabled until the request is loaded asynchronously. This is done by passing the request
object from the useAuthRequest
hook to the disabled
prop of the button component.
An example button component is shown below:
<Button
title="Sign in with Google"
disabled={!request}
onPress={() => {
promptAsync();
}}
/>
In the code snippet below, you can see a minimal working example of the AuthSession API with Google provider. It stores the access token retrieved from the successful authentication request to fetch the user's public information and display it on the app screen.
import { useEffect, useState } from "react";
import { StyleSheet, Text, View, Button } from "react-native";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
WebBrowser.maybeCompleteAuthSession();
export default function App() {
const [token, setToken] = useState("");
const [userInfo, setUserInfo] = useState(null);
const [request, response, promptAsync] = Google.useAuthRequest({
androidClientId: "GOOGLE_GUID.apps.googleusercontent.com",
iosClientId: "GOOGLE_GUID.apps.googleusercontent.com",
});
useEffect(() => {
if (response?.type === "success") {
setToken(response.authentication.accessToken);
getUserInfo();
}
}, [response, token]);
const getUserInfo = async () => {
try {
const response = await fetch(
"https://www.googleapis.com/userinfo/v2/me",
{
headers: { Authorization: `Bearer ${token}` },
}
);
const user = await response.json();
setUserInfo(user);
} catch (error) {
// Add your own error handler here
}
};
return (
<View style={styles.container}>
{userInfo === null ? (
<Button
title="Sign in with Google"
disabled={!request}
onPress={() => {
promptAsync();
}}
/>
) : (
<Text style={styles.text}>{userInfo.name}</Text>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
text: {
fontSize: 20,
fontWeight: "bold",
},
});
For a development build, see Use development builds for further instructions on how to start the development server or run npx expo run:android
or npx expo run:ios
command to test the native project locally.
For a web app, you need to create a webClientId
. Follow the steps below from the Google Cloud console to generate it:
https://localhost:19006
and https://yourwebsite.com
.https://localhost:19006
and https://yourwebsite.com
.After creating the client ID, you can use it in the webClientId
property of the Google.useAuthRequest
hook.
For testing the web app, start your project with the following command:
-
npx expo start --web --https
Error 401: invalid_client The OAuth client was not found
Make sure that you have added the correct iosClientId
in the Google.useAuthRequest
hook and follow the pattern: GOOGLE_GUID.apps.googleusercontent.com
where GOOGLE_GUID
is the unique ID generated.
For a development build or projects using EAS, the URI scheme is automatically added.
For bare workflow, your project needs to conform to the URI scheme matching your android.package
for Android and ios.bundleIdentifier
for iOS. You can do that by running the following command for each platform:
-
npx uri-scheme add your-android.package --android
-
npx uri-scheme add your-ios.bundleIdentifier --ios