Universal 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.
The functionality covered in this page is available in the licensed version. You can get a license here ⭐️.
-
On Android, it is built on top of the new Credential Manager APIs.
-
On Apple (iOS and macOS), it is built on top of the Google Sign In SDK for iOS and macOS.
-
On the web, it covers both the One-tap flow and the Google Sign-In button. Learn more.
Usage
You can copy-paste this snippet to get a complete sign-in flow quickly. For most apps, authenticate is the API to use.
import {
GoogleOneTapSignIn,
GoogleLogoButton,
} from '@react-native-google-signin/google-signin';
<GoogleLogoButton
onPress={authenticateWithGoogle}
label="Sign in with Google"
/>;
export const authenticateWithGoogle = async () => {
GoogleOneTapSignIn.configure({
webClientId: 'autoDetect',
}); // move this to after your app starts
const { user, error, isCancelled } = await GoogleOneTapSignIn.authenticate();
if (user) {
// use user
} else if (isCancelled) {
// the user cancelled the flow
} else if (error) {
// handle error.code
}
};
Note that on Apple and Android, you can combine the Universal sign in methods with methods from the Original Google Sign In. To do that, use the Universal 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.
Main Methods
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. authenticate 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 also need to provide the iosClientId parameter. All other parameters are optional.
GoogleOneTapSignIn.configure({
webClientId: 'autoDetect',
});
authenticate
signature on native platforms: (params?: OneTapAuthenticateParams) => Promise<OneTapAuthenticateResponse>
signature on web: (params: OneTapAuthenticateParams, callbacks: WebOneTapAuthenticateCallbacks) => void
This is the recommended way to authenticate a user.
On Android, iOS and macOS, authenticate runs the complete authentication sequence for you. It checks Play Services on Android, tries signIn to restore a saved credential without user interaction, calls createAccount if no saved credential is found, and finally calls presentExplicitSignIn if the user still needs to pick or add an account. You only handle the final outcome: user, error, or isCancelled. It does not return noSavedCredentialFound; that case is handled internally.
On web, authenticate initializes the Google Identity Services One Tap listener through the web signIn implementation. It reports success, cancellation, and typed errors through onResponse. The method is callback-based because the Google Identity Services SDK can report that One Tap is unavailable and still later return a successful sign-in from the Google Sign-In button. The onResponse callback may be called more than once.
import {
GoogleOneTapSignIn,
statusCodes,
} from '@react-native-google-signin/google-signin';
const { user, error, isCancelled } = await GoogleOneTapSignIn.authenticate();
if (user) {
// use user
} else if (isCancelled) {
// the user cancelled the flow
} else if (error) {
switch (error.code) {
case statusCodes.PLAY_SERVICES_NOT_AVAILABLE:
// Android: play services not available or outdated.
// Web: Google Client Library is not loaded yet.
break;
default:
// something else happened
}
}
See Web support for the web callback example.
requestAuthorization
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.
| Platform | Behavior |
|---|---|
| Android | Presents a modal that asks user for additional access to their Google account. Uses AuthorizationRequest.Builder. |
| Apple | Calls 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. |
| Web | Not implemented at the moment. |
UI screenshots
| Android | iOS |
|---|---|
![]() | ![]() |
signOut
signature: () => Promise<null>
Signs out the current user. This disables the automatic sign-in.
Returns a Promise that resolves with null or rejects in case of error.
await GoogleOneTapSignIn.signOut();
Automatic webClientId & iosClientId detection
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:
- Add
WEB_CLIENT_IDentry to theGoogleService-Info.plistfile.
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>
- pass
"autoDetect"as thewebClientIdparameter.
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.
Advanced methods
signIn
signature: (params?: OneTapSignInParams) => Promise<OneTapResponse>
| Platform | Behavior |
|---|---|
| Android | Attempts to sign in user automatically, without interaction. Docs. |
| Apple | Attempts to restore a previous user sign-in without interaction. Docs. |
| Web | Attempts to sign in user automatically, without interaction. Docs. If none is found, presents a sign-in UI. Read below for web support. |
If there is no user that was previously signed in, the returned 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.
Most apps should use authenticate. Use signIn directly only if you need to control this first step yourself.
UI screenshots
| Android | iOS | Web |
|---|---|---|
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
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.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
}
}
};
createAccount
signature: (params?: OneTapCreateAccountParams) => Promise<OneTapResponse>
| Platform | Behavior |
|---|---|
| Android | Starts 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). |
| Apple | Starts 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). |
| Web | Presents 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.
Most apps should use authenticate. Use createAccount directly only if you need to control this step yourself.
UI screenshots
| Android | iOS | Web |
|---|---|---|
![]() | ![]() | ![]() |
await GoogleOneTapSignIn.createAccount();
presentExplicitSignIn
signature: (params?: OneTapExplicitSignInParams) => Promise<OneTapExplicitSignInResponse>
| Platform | Behavior |
|---|---|
| Android | Presents the sign in dialog explicitly. This is useful 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 prompts the user to add a Google account. |
| Apple | Starts an interactive sign-in flow. Same as createAccount. |
| Web | Presents a one-tap prompt. Same as createAccount. |
Preferably, call this method only as a reaction to when user taps a sign in button.
Most apps should use authenticate. Use presentExplicitSignIn directly only if you need to control the explicit sign-in step yourself.
UI screenshots
| Android | iOS | Web |
|---|---|---|
![]() | ![]() | ![]() |
await GoogleOneTapSignIn.presentExplicitSignIn();
checkPlayServices
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_AVAILABLEerror code, and more information inuserInfofield (see below).
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).
On Android, the 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.
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

- Apple: Play Services are an Android-only concept and are not needed on Apple. Hence, the method always resolves.
- Web: resolves when the Google Client Library is loaded, rejects otherwise.
await GoogleOneTapSignIn.checkPlayServices();
revokeAccess
signature: (emailOrUniqueId: string) => Promise<null>
Revokes access given to the current application and signs the user out. Use when a user deletes their account in your app. On the web, you need to provide the id or email of the user. On Android and Apple, the emailOrUniqueId parameter does not have any effect.
Returns a Promise that resolves with null or rejects in case of error.
await GoogleOneTapSignIn.revokeAccess(user.id);
clearCachedAccessToken
signature: (accessTokenString: string) => Promise<null>
This method is only needed on Android. You may run into a 401 Unauthorized error when an access token is invalid. Call this method to remove the token from local cache and then call requestAuthorization() to get a fresh access token. Calling this method on Apple does nothing and always resolves. This is because on Apple, requestAuthorization() always returns valid tokens, refreshing them first if they have expired or are about to expire (see docs).
Utility Functions
There are 4 helper functions available:
These helpers are useful when you call the advanced methods directly. authenticate returns user, error, or isCancelled directly.
isErrorWithCodefor processing errorsisSuccessResponsefor checking if a response represents a successful operation. Same as checkingresponse.type === 'success'.isNoSavedCredentialFoundResponsefor checking if a response represents no saved credentials case. Same as checkingresponse.type === 'noSavedCredentialFound'.isCancelledResponsefor checking if a response represents user cancellation case. Same as checkingresponse.type === 'cancelled'.








