Skip to main content

Modern Google sign in

This is Google's recommended way to implement Google Sign In. This API is available on Android, iOS, macOS and web (with a little extra work described below). It is a replacement for the Original Google sign in. The module APIs are named GoogleOneTapSignIn for historical reasons.

tip

The functionality covered in this page is only available to sponsors️. It takes just a few clicks to get access ❤️.

This module is being actively developed, and new features are added regularly.

Note that on Apple and Android, you can combine the Modern Sign In methods with those one from the Original Google Sign In. To do that, use the Modern sign in to sign in the user. Then call signInSilently() and then (for example) getCurrentUser() to get the current user's information. However, this shouldn't be necessary because this module should cover all your needs. Please open an issue if that's not the case.

example of importing the module
import {
GoogleOneTapSignIn,
statusCodes,
type OneTapUser,
} from '@react-native-google-signin/google-signin';

configure

signature: (params: OneTapConfigureParams) => void

It is mandatory to call configure before attempting to call any of the sign-in methods. This method is synchronous, meaning you can call e.g. signIn right after it. Typically, you would call configure only once, soon after your app starts.

webClientId is a required parameter. Use "autoDetect" for automatic webClientId detection. If you're using neither Expo nor Firebase, you need to provide the iosClientId parameter. All other parameters are optional.

Example of calling the configure() method
GoogleOneTapSignIn.configure({
webClientId: 'autoDetect',
});

checkPlayServices

✨since v17.3.0

signature: (showErrorResolutionDialog?: boolean): Promise<PlayServicesInfo>

The behavior of checkPlayServices varies across platforms:

  • Android: The function resolves if the device has Play Services installed and their version is >= the minimum required version. Otherwise, it rejects with statusCodes.PLAY_SERVICES_NOT_AVAILABLE error code, and more information in userInfo field (see below).

On Android, presence of up-to-date Google Play Services is required to call any of the provided authentication and authorization methods. It is therefore necessary to call checkPlayServices any time prior to calling the authentication / authorization methods and only call those if checkPlayServices is successful.

The showErrorResolutionDialog parameter (default true) controls whether a dialog that helps to resolve an error is shown (only in case the error is user-resolvable).

Some errors are user-resolvable (e.g. when Play Services are outdated, or disabled) while other errors cannot be resolved (e.g. when the phone doesn't ship Play Services at all - which is the case with some device vendors).

Dialog screenshots

prompt install prompt enable

  • Apple: Play Services are an Android-only concept and are not needed on Apple. Hence, the method always resolves with:
{
minRequiredVersion: -1,
installedVersion: -1,
}
  • Web: resolves (with the same value as on Apple) when the Google Client Library is loaded, rejects otherwise.
Example of showPlayServicesUpdateDialog() method
await GoogleOneTapSignIn.showPlayServicesUpdateDialog();

signIn

signature: (params?: OneTapSignInParams) => Promise<OneTapResponse>

PlatformBehavior
AndroidAttempts to sign in user automatically, without interaction. Docs.
AppleAttempts to restore a previous user sign-in without interaction. Docs.
WebAttempts to sign in user automatically, without interaction. Docs. If none is found, presents a sign-in UI. Read below for web support.

Returns a Promise that resolves with OneTapResponse or rejects in case of error.

If there is no user that was previously signed in, the promise resolves with NoSavedCredentialFound object. In that case, you can call createAccount to start a flow to create a new account. You don't need to call signIn as a response to a user action - you can call it when your app starts or when suitable.

UI screenshots
AndroidiOSWeb
No UI, no user interaction the first time. If user has signed up previously, they will see this:
(no UI, no user interaction)The prompt presented the first time:
If user has signed in previously, they will see this:

Example code snippet

Example of calling the signIn() method
import {
GoogleOneTapSignIn,
statusCodes,
isErrorWithCode,
isSuccessResponse,
isNoSavedCredentialFoundResponse,
} from '@react-native-google-signin/google-signin';

// Somewhere in your code
const signIn = async () => {
try {
await GoogleOneTapSignIn.checkPlayServices();
const response = await GoogleOneTapSignIn.signIn();

if (isSuccessResponse(response)) {
// read user's info
console.log(response.data);
} else if (isNoSavedCredentialFoundResponse(response)) {
// Android and Apple only.
// No saved credential found (user has not signed in yet, or they revoked access)
// call `createAccount()`
}
} catch (error) {
console.error(error);
if (isErrorWithCode(error)) {
switch (error.code) {
case statusCodes.ONE_TAP_START_FAILED:
// Android-only, you probably have hit rate limiting.
// You can still call `presentExplicitSignIn` in this case.
break;
case statusCodes.PLAY_SERVICES_NOT_AVAILABLE:
// Android: play services not available or outdated.
// Get more details from `error.userInfo`.
// Web: when calling an unimplemented api (requestAuthorization)
// or when the Google Client Library is not loaded yet.
break;
default:
// something else happened
}
} else {
// an error that's not related to google sign in occurred
}
}
};

Utility Functions

tip

There are 4 helper functions available:

  • isErrorWithCode for processing errors
  • isSuccessResponse for checking if a response represents a successful operation. Same as checking response.type === 'success'.
  • isNoSavedCredentialFoundResponse for checking if a response represents no saved credentials case. Same as checking response.type === 'noSavedCredentialFound'.
  • isCancelledResponse for checking if a response represents user cancellation case. Same as checking response.type === 'cancelled'.

createAccount

signature: (params?: OneTapCreateAccountParams) => Promise<OneTapResponse>

PlatformBehavior
AndroidStarts a flow to sign in with your app for the first time (to create a user account). It offers a list of user accounts to choose from (multiple Google accounts can be logged in on the device).
AppleStarts an interactive sign-in flow. Docs. It offers a list of user accounts to choose from (multiple Google accounts can be logged in on the device).
WebPresents a one-tap prompt and waits for user interaction (it will not sign in automatically). The prompt has a slightly different styling than with signIn (configrable via the context param). Read below for web support.

You don't need to call createAccount as a response to a user action - you can call it some time after your app starts (Though keep in mind the way the dialog is presented on iOS might be inconvenient to users if they didn't ask for it) or when suitable.

Use createAccount if signIn resolved with NoSavedCredentialFound result, as indicated in the code snippet above.

Returns a Promise that resolves with OneTapResponse or rejects in case of error.

UI screenshots
AndroidiOSWeb
await GoogleOneTapSignIn.createAccount({
nonce: 'your_nonce', // nonce is supported on all platforms!
});

presentExplicitSignIn

✨since v14.2.0

signature: (params?: OneTapExplicitSignInParams) => Promise<OneTapExplicitSignInResponse>

PlatformBehavior
AndroidPresents the sign in dialog explicitly. This is useful when the user has hit rate limiting (ONE_TAP_START_FAILED) and the one-tap flow is thus not available, or if both signIn and createAccount resolve with NoSavedCredentialFound object - which happens (in the unlikely case) when no Google account is present on the device. This will prompt the user to add a Google account.
AppleStarts an interactive sign-in flow. Same as createAccount.
WebPresents a one-tap prompt. Same as createAccount.

Preferably, call this method only as a reaction to when user taps a "sign in with Google" button.

UI screenshots
AndroidiOSWeb
await GoogleOneTapSignIn.presentExplicitSignIn({
nonce: 'your_nonce', // nonce is supported on all platforms!
});

signOut

signature: (emailOrUniqueId: string) => Promise<null>

Signs out the current user. On the web, you need to provide the id or email of the user. On Android and Apple, this parameter does not have any effect.

Returns a Promise that resolves with null or rejects in case of error.

await GoogleOneTapSignIn.signOut(user.id);

requestAuthorization

✨since v15.0.0

signature: (params: RequestAuthorizationParams) => Promise<AuthorizationResponse>

The underlying Android SDK separates authentication and authorization - that means that on Android you can request an access token and call Google APIs on behalf of the user without previously signing the user in.

This method is used to request extra authorization from the user. Use this on Android to obtain server-side access (offline access) to the user's data or for requesting an access token that has access to additional scopes.

PlatformBehavior
AndroidPresents a modal that asks user for additional access to their Google account. Uses AuthorizationRequest.Builder.
AppleCalls addScopes. The resulting accessToken has access to the requested scopes. Use this if you want to read more user metadata than just the basic info.
WebNot implemented at the moment.

There are minor differences between the Android and Apple implementations stemming from the underlying Google SDKs. For example, Apple returns all granted scopes, while Android may only return the scopes that were requested.

UI screenshots
AndroidiOS

Automatic webClientId & iosClientId detection

✨since v15.2.0 for webClientId, 18.2.0 for iosClientId

If you use Expo (with the config plugin and prebuild), or if you're using Firebase, you don't need to provide the iosClientId parameter to the configure method.

Additionally, this module can automatically detect the webClientId from Firebase's configuration file (does not work on web where you need to provide it explicitly).

This is useful if you're using Firebase and want to avoid manually setting the webClientId in your code, especially if you have multiple environments (e.g. staging, production).

To use this feature:

  1. Add WEB_CLIENT_ID entry to the GoogleService-Info.plist file.

On Android, the google-services.json file already contains the web client ID information. Unfortunately, it's not the case on iOS, so we need to add it ourselves.

Open the GoogleService-Info.plist in your favorite text editor and add the following:

<key>WEB_CLIENT_ID</key>
<string>your-web-client-id.apps.googleusercontent.com</string>
  1. pass "autoDetect" as the webClientId parameter.
tip

As explained above, iosClientId can also be detected automatically - simply do not pass any iosClientId value. The reason webClientId is a required parameter is API uniformity across all platforms.


Web support

Providing a unified API across all platforms is a bit more tricky than it may seem. The web experience is different from the mobile one, and so are the underlying APIs.

On the web, the GoogleOneTapSignIn sign in functions are not Promise-based but callback-based as seen below. That means they return void and you need to provide callbacks for success and error handling.

Still, the parameter and result types are the same as for native, allowing to reuse the logic for both success and error handling across all platforms.

note

The implementation has been migrated to FedCM though you can disable this via use_fedcm_for_prompt parameter.

To implement web support, follow these steps:

  1. Call GoogleOneTapSignIn.signIn upon page load. This attempts to present the One-tap UI. It also sets up a listener for authentication events and calls the onSuccess callback when the user signs in (either with the One-tap flow or the Sign-In button).

If you do not want to present the one-tap UI, pass skipPrompt: true in the OneTapSignInParams object. This only sets up the listener for authentication events, and then relies on the user signing in via the WebGoogleSigninButton.

warning

You should display the One Tap UI on page load or other window events, instead of it being displayed by a user action (e.g. a button press). Otherwise, you may get a broken UX. Users may not see any UI after a user action, due to globally opt-out, cool-down, or no Google session.

useEffect(() => {
GoogleOneTapSignIn.configure({
webClientId,
iosClientId: config.iosClientId,
});
if (Platform.OS === 'web') {
GoogleOneTapSignIn.signIn(
{
ux_mode: 'popup',
},
{
onResponse: (response) => {
if (response.type === 'success') {
console.log(response.data);
}
},
onError: (error) => {
// handle error
},
momentListener: (moment) => {
console.log('moment', moment);
},
},
);
}
}, []);

Optionally, you can provide a momentListener callback function. The callback is called when important events take place. See reference.

  1. Render the WebGoogleSigninButton component

One-tap UI may not always be available: This happens if you disable it (skipPrompt), when user has opted out or when they cancel the prompt several times in a row, entering the cooldown period.

WebGoogleSigninButton serves as a fallback. Tapping it opens the regular Google Sign-In dialog (or redirect, based on ux_mode param). When user signs in, the onResponse callback is called.

info

The reason the GoogleOneTapSignIn.signIn api is callback-based rather than promise-based is that it's possible to get into an "error" state (when one-tap is not available) and later get a successful sign in from the button flow. Because of how the Google Sign In for web SDK is done, modeling this with a promise-based api is not possible.