# React Native Google Sign In > Google sign in for Expo and React Native apps This file contains all documentation content in a single document following the llmstxt.org standard. ## API reference ## Universal sign in module ### AuthorizationResponse > **AuthorizationResponse** = [`CancelledResponse`](#cancelledresponse) \| [`AuthorizationSuccessResponse`](#authorizationsuccessresponse) The response object of `requestAuthorization`. Either the user cancelled the flow or they successfully gave authorization. --- ### AuthorizationSuccessResponse > **AuthorizationSuccessResponse** = \{ `data`: \{ `accessToken`: `string`; `grantedScopes`: `string`[]; `serverAuthCode`: `string` \| `null`; \}; `type`: `"success"`; \} An object that contains an access token that has access to the `grantedScopes`. It contains also the `serverAuthCode` if `offlineAccess` was requested. On iOS, you can also obtain `serverAuthCode` by calling `createAccount()`. #### Properties | Property | Type | | ------------------------ | ------------------------------------------------------------------------------------------------- | | `data` | \{ `accessToken`: `string`; `grantedScopes`: `string`[]; `serverAuthCode`: `string` \| `null`; \} | | `data.accessToken` | `string` | | `data.grantedScopes` | `string`[] | | `data.serverAuthCode` | `string` \| `null` | | `type` | `"success"` | --- ### EnableAppCheckParams > **EnableAppCheckParams** = \{ `debugProviderAPIKey?`: `string`; \} Parameters for enabling [App Check](/docs/security#appcheck). Provide `debugProviderAPIKey` to enable App Check with [debug provider](https://developers.google.com/identity/sign-in/ios/appcheck/debug-provider). #### Properties | Property | Type | | ------------------------------------------------------- | -------- | | `debugProviderAPIKey?` | `string` | --- ### OneTapConfigureParams > **OneTapConfigureParams** = [`ClientIdOrPlistPath`](#clientidorplistpath) & \{ `hostedDomain?`: `string`; `logLevel?`: `"debug"` \| `"info"` \| `"warn"`; `openIdRealm?`: `string`; `profileImageSize?`: `number`; `scopes?`: `string`[]; `webClientId`: `WebClientId`; \} `webClientId` is the most important parameter in the configuration. It is required. #### Type Declaration | Name | Type | Description | | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `hostedDomain?` | `string` | iOS only. Specifies a hosted domain restriction. By setting this, authorization will be restricted to accounts of the user in the specified domain. | | `logLevel?` | `"debug"` \| `"info"` \| `"warn"` | Web only. Controls debug logging in browser console. This is implemented in Google's web SDK and is not part of their public API so it may change or be removed at any time. | | `openIdRealm?` | `string` | iOS only. The OpenID2 realm of the home web server. This allows Google to include the user's OpenID Identifier in the OpenID Connect ID token. | | `profileImageSize?` | `number` | iOS only. The desired height and width of the profile image. **Default** `120px` | | `scopes?` | `string`[] | iOS only. The Google API scopes to request access to. Use `requestAuthorization` to request additional scopes on Android. **Default** `["email", "profile"]` | | `webClientId` | `WebClientId` | The web client ID obtained from Google Cloud console. In the Universal module only, pass `autoDetect` to automatically determine the value from Firebase config file. | --- ### OneTapCreateAccountParams > **OneTapCreateAccountParams** = [`OneTapSignInParams`](#onetapsigninparams) & \{ `accountName?`: `string`; `requestVerifiedPhoneNumber?`: `boolean`; \} #### Type Declaration | Name | Type | Description | | ----------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `accountName?` | `string` | iOS only. An account name present on the device that should be used. **Example** `your_email@gmail.com` | | `requestVerifiedPhoneNumber?` | `boolean` | Android only. Whether to request for a verified phone number during sign-ups. Requesting it doesn't guarantee that it will be provided in the response. **Default** `false` | --- ### OneTapExplicitSignInParams > **OneTapExplicitSignInParams** = [`OneTapSignInParams`](#onetapsigninparams) & \{ `accountName?`: `string`; \} #### Type Declaration | Name | Type | Description | | -------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `accountName?` | `string` | iOS only. An account name present on the device that should be used. **Example** `your_email@gmail.com` | --- ### OneTapExplicitSignInResponse > **OneTapExplicitSignInResponse** = [`OneTapSuccessResponse`](#onetapsuccessresponse) \| [`CancelledResponse`](#cancelledresponse) --- ### OneTapResponse > **OneTapResponse** = [`OneTapSuccessResponse`](#onetapsuccessresponse) \| [`CancelledResponse`](#cancelledresponse) \| [`NoSavedCredentialFound`](#nosavedcredentialfound) The response object for OneTap's `signIn` and `createAccount`. --- ### OneTapSignInParams > **OneTapSignInParams** = \{ `nonce?`: `string`; `skipPrompt?`: `boolean`; \} & `ReducedWebSignInOptions` Learn more about additional web-only parameters at [Google's reference documentation](https://developers.google.com/identity/gsi/web/reference/js-reference#IdConfiguration). #### Type Declaration | Name | Type | Description | | ------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `nonce?` | `string` | A cryptographically random value used to mitigate replay attacks. Supported on all platforms. | | `skipPrompt?` | `boolean` | Web only. When calling any of the sign-in methods, a prompt is displayed by default on the top-right of the web page. Set this to true to only allow signing in via the `WebGoogleSigninButton`. **Default** `false` | --- ### OneTapSuccessResponse > **OneTapSuccessResponse** = \{ `data`: [`OneTapUser`](#onetapuser); `type`: `"success"`; \} The response object when the user successfully signs in. #### Properties | Property | Type | | -------------------------- | --------------------------- | | `data` | [`OneTapUser`](#onetapuser) | | `type` | `"success"` | --- ### OneTapUser > **OneTapUser** = \{ `credentialOrigin`: `CredentialResponse`\[`"select_by"`\]; `idToken`: `string`; `serverAuthCode`: `string` \| `null`; `user`: \{ `email`: `string` \| `null`; `familyName`: `string` \| `null`; `givenName`: `string` \| `null`; `id`: `string`; `name`: `string` \| `null`; `phoneNumber`: `string` \| `null`; `photo`: `string` \| `null`; \}; \} #### Properties | Property | Type | Description | | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `credentialOrigin` | `CredentialResponse`\[`"select_by"`\] | The credential origin. This is the method that was used to sign in the user. On native platforms, this is always "user". On the web it's a value from a union type. | | `idToken` | `string` | - | | `serverAuthCode` | `string` \| `null` | iOS only. Not null only if a valid `webClientId` and `offlineAccess: true` was specified in `configure()`. Call `requestAuthorization()` to obtain it on Android. | | `user` | \{ `email`: `string` \| `null`; `familyName`: `string` \| `null`; `givenName`: `string` \| `null`; `id`: `string`; `name`: `string` \| `null`; `phoneNumber`: `string` \| `null`; `photo`: `string` \| `null`; \} | - | | `user.email` | `string` \| `null` | - | | `user.familyName` | `string` \| `null` | - | | `user.givenName` | `string` \| `null` | - | | `user.id` | `string` | An immutable identifier for the user. Unique among all Google accounts and never reused (user's email can change, this value cannot). | | `user.name` | `string` \| `null` | - | | `user.phoneNumber` | `string` \| `null` | Android only, and only for `createAccount`. Requires setting `requestVerifiedPhoneNumber` to `true`. | | `user.photo` | `string` \| `null` | - | --- ### PlayServicesInfo > **PlayServicesInfo** = \{ `installedVersion`: `number`; `minRequiredVersion`: `number`; \} The response object for successful `checkPlayServices` call. It denotes that the necessary prerequisites for calling the module in methods are met. #### Properties | Property | Type | | ---------------------------------------------------- | -------- | | `installedVersion` | `number` | | `minRequiredVersion` | `number` | --- ### RequestAuthorizationParams > **RequestAuthorizationParams** = \{ `accountName?`: `string`; `hostedDomain?`: `string`; `offlineAccess?`: \{ `enabled`: `boolean`; `forceCodeForRefreshToken?`: `boolean`; \}; `scopes`: `string`[]; \} Learn more in the [guide](/docs/one-tap#requestauthorization). #### Properties | Property | Type | Description | | ------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `accountName?` | `string` | Android only. Specifies an account on the device that should be used. | | `hostedDomain?` | `string` | Android only. Specifies a hosted domain restriction. By setting this, authorization will be restricted to accounts of the user in the specified domain. | | `offlineAccess?` | \{ `enabled`: `boolean`; `forceCodeForRefreshToken?`: `boolean`; \} | - | | `offlineAccess.enabled` | `boolean` | Whether to enable offline access. If enabled, `serverAuthCode` will be returned in the response. | | `offlineAccess.forceCodeForRefreshToken?` | `boolean` | Android only. If true, the granted code can be exchanged for an access token and a refresh token. Only use true if your server has suffered some failure and lost the user's refresh token. | | `scopes` | `string`[] | The Google API scopes to request access to. See [scopes docs](/docs/integration-notes#additional-scopes). | --- ### GoogleOneTapSignIn > `const` **GoogleOneTapSignIn**: complex type, see below The entry point of the Universal Sign In API, exposed as `GoogleOneTapSignIn`. On the web, the signatures of `signIn`, `presentExplicitSignIn`, and `createAccount` are callback-based and on native they are Promise-based. Read more in the [guide](/docs/one-tap#web-support). #### Type Declaration | Name | Type | | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | | `configure` | (`params`: [`OneTapConfigureParams`](#onetapconfigureparams)) => `void` | | `checkPlayServices` | (`showErrorResolutionDialog`?: `boolean`) => `Promise`\<[`PlayServicesInfo`](#playservicesinfo)\> | | `enableAppCheck` | (`params`?: [`EnableAppCheckParams`](#enableappcheckparams)) => `Promise`\<`null`\> | | `signIn` | (`params?`: [`OneTapSignInParams`](#onetapsigninparams)) => `Promise`\<[`OneTapResponse`](#onetapresponse)\> | | `createAccount` | (`params?`: [`OneTapCreateAccountParams`](#onetapcreateaccountparams)) => `Promise`\<[`OneTapResponse`](#onetapresponse)\> | | `clearCachedAccessToken()` | (`tokenString`: `string`) => `Promise`\<`null`\> | `GoogleSignin.clearCachedAccessToken` | | `presentExplicitSignIn` | (`params?`: [`OneTapExplicitSignInParams`](#onetapexplicitsigninparams)) => `Promise`\<[`OneTapExplicitSignInResponse`](#onetapexplicitsigninresponse)\> | | `requestAuthorization` | (`options`: [`RequestAuthorizationParams`](#requestauthorizationparams)) => `Promise`\<[`AuthorizationResponse`](#authorizationresponse)\> | | `signOut` | () => `Promise`\<`null`\> | | `revokeAccess` | (`emailOrUniqueId`: `string`) => `Promise`\<`null`\> | ## Original Google sign in ### AddScopesParams > **AddScopesParams** = \{ `scopes`: `string`[]; \} #### Properties | Property | Type | Description | | ---------------------------- | ---------- | ------------------------------------------------------------------------------ | | `scopes` | `string`[] | The Google API scopes to request access to. **Default** `["email", "profile"]` | --- ### ConfigureParams > **ConfigureParams** = [`ClientIdOrPlistPath`](#clientidorplistpath) & \{ `accountName?`: `string`; `forceCodeForRefreshToken?`: `boolean`; `hostedDomain?`: `string`; `offlineAccess?`: `boolean`; `openIdRealm?`: `string`; `profileImageSize?`: `number`; `scopes?`: `string`[]; `webClientId?`: `WebClientId`; \} #### Type Declaration | Name | Type | Description | | --------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `accountName?` | `string` | Android only. An account name that should be prioritized. | | `forceCodeForRefreshToken?` | `boolean` | Android only. Only set to `true` if your server has suffered some failure and lost the user's refresh token. | | `hostedDomain?` | `string` | Specifies a hosted domain restriction. By setting this, authorization will be restricted to accounts of the user in the specified domain. | | `offlineAccess?` | `boolean` | Must be `true` if you wish to access user APIs on behalf of the user from your own server. When offline access is requested, an authorization code is returned so the server can use the authorization code to exchange for access token and refresh token. The access token allows the server to access Google data on behalf of the user. | | `openIdRealm?` | `string` | iOS only. The OpenID2 realm of the home web server. This allows Google to include the user's OpenID Identifier in the OpenID Connect ID token. | | `profileImageSize?` | `number` | iOS only. The desired height and width of the profile image. **Default** `120px` | | `scopes?` | `string`[] | The Google API scopes to request access to. **Default** `["email", "profile"]` | | `webClientId?` | `WebClientId` | The web client ID obtained from Google Cloud console. Required for offline access. | --- ### GetTokensResponse > **GetTokensResponse** = \{ `accessToken`: `string`; `idToken`: `string`; \} #### Properties | Property | Type | | -------------------------------------- | -------- | | `accessToken` | `string` | | `idToken` | `string` | --- ### HasPlayServicesParams > **HasPlayServicesParams** = \{ `showPlayServicesUpdateDialog?`: `boolean`; \} #### Properties | Property | Type | Description | | ------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `showPlayServicesUpdateDialog?` | `boolean` | Whether to show a dialog that prompts the user to install Google Play Services, if they don't have them installed. **Default** `true` | --- ### SignInParams > **SignInParams** = \{ `loginHint?`: `string`; `nonce?`: `string`; \} #### Properties | Property | Type | Description | | ----------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `loginHint?` | `string` | iOS only. The user's ID, or email address, to be prefilled in the authentication UI if possible. [See docs here](https://developers.google.com/identity/sign-in/ios/reference/Classes/GIDSignIn#-signinwithpresentingviewcontroller:hint:completion:). | | `nonce?` | `string` | iOS only. A cryptographically random value used to mitigate replay attacks. Only available in the paid version. For support across all platforms, use the Universal sign in module. | --- ### SignInResponse > **SignInResponse** = [`SignInSuccessResponse`](#signinsuccessresponse) \| [`CancelledResponse`](#cancelledresponse) --- ### SignInSilentlyResponse > **SignInSilentlyResponse** = [`SignInSuccessResponse`](#signinsuccessresponse) \| [`NoSavedCredentialFound`](#nosavedcredentialfound) The response object for calling `signInSilently`. Either the user details are available (without user interaction) or there was no saved credential found. --- ### SignInSuccessResponse > **SignInSuccessResponse** = \{ `data`: [`User`](#user); `type`: `"success"`; \} The response object when the user signs in successfully. #### Properties | Property | Type | Description | | -------------------------- | --------------- | ----------------- | | `data` | [`User`](#user) | The user details. | | `type` | `"success"` | - | --- ### User > **User** = \{ `idToken`: `string` \| `null`; `scopes`: `string`[]; `serverAuthCode`: `string` \| `null`; `user`: \{ `email`: `string`; `familyName`: `string` \| `null`; `givenName`: `string` \| `null`; `id`: `string`; `name`: `string` \| `null`; `photo`: `string` \| `null`; \}; \} #### Properties | Property | Type | Description | | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `idToken` | `string` \| `null` | JWT (JSON Web Token) that serves as a secure credential for your user's identity. | | `scopes` | `string`[] | The Google API scopes that the user granted access to. | | `serverAuthCode` | `string` \| `null` | Code that you can securely send to your server to exchange for an access and refresh token. Use the access token to call Google APIs on behalf of the user and, optionally, store the refresh token to acquire a new access token when the access token expires. Not null only if a valid `webClientId` and `offlineAccess` was enabled in `configure()`. | | `user` | \{ `email`: `string`; `familyName`: `string` \| `null`; `givenName`: `string` \| `null`; `id`: `string`; `name`: `string` \| `null`; `photo`: `string` \| `null`; \} | - | | `user.email` | `string` | - | | `user.familyName` | `string` \| `null` | - | | `user.givenName` | `string` \| `null` | - | | `user.id` | `string` | - | | `user.name` | `string` \| `null` | - | | `user.photo` | `string` \| `null` | - | --- ### GoogleSignin > `const` **GoogleSignin**: complex type, see below The entry point of the Google Sign In API, exposed as `GoogleSignin`. #### Type Declaration | Name | Type | | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `addScopes()` | (`options`: [`AddScopesParams`](#addscopesparams)) => `Promise`\<`null` \| [`SignInResponse`](#signinresponse)\> | | `clearCachedAccessToken()` | (`tokenString`: `string`) => `Promise`\<`null`\> | | `configure()` | (`options?`: [`ConfigureParams`](#configureparams)) => `void` | | `enableAppCheck()` | (`params?`: [`EnableAppCheckParams`](#enableappcheckparams)) => `Promise`\<`null`\> | | `getCurrentUser()` | () => `null` \| [`User`](#user) | | `getTokens()` | () => `Promise`\<[`GetTokensResponse`](#gettokensresponse)\> | | `hasPlayServices()` | (`options?`: [`HasPlayServicesParams`](#hasplayservicesparams)) => `Promise`\<`boolean`\> | | `hasPreviousSignIn()` | () => `boolean` | | `revokeAccess()` | () => `Promise`\<`null`\> | | `signIn()` | (`options`: [`SignInParams`](#signinparams)) => `Promise`\<[`SignInResponse`](#signinresponse)\> | | `signInSilently()` | () => `Promise`\<[`SignInSilentlyResponse`](#signinsilentlyresponse)\> | | `signOut()` | () => `Promise`\<`null`\> | ## Constants ### statusCodes > `const` **statusCodes**: `Readonly`\<\{ `IN_PROGRESS`: `string`; `ONE_TAP_START_FAILED`: `string`; `PLAY_SERVICES_NOT_AVAILABLE`: `string`; \}\> Read more about the meaning of the error codes in the [guide](/docs/errors). ## Functions ### isCancelledResponse() > **isCancelledResponse**(`response`: [`OneTapResponse`](#onetapresponse)): `response is CancelledResponse` TypeScript helper to check if a response is a `cancelled` response. This is the same as checking if the `response.type === "cancelled"`. Use this if you prefer to use a function instead of comparing with a raw string. It supports both One Tap and Original Google Sign In responses. #### Parameters | Parameter | Type | | ---------- | ----------------------------------- | | `response` | [`OneTapResponse`](#onetapresponse) | #### Returns `response is CancelledResponse` #### Example ```ts const response = await GoogleOneTapSignIn.createAccount(); if (isCancelledResponse(response)) { // handle cancelled response } ``` --- ### isErrorWithCode() > **isErrorWithCode**(`error`: `any`): `error is NativeModuleError` TypeScript helper to check if an object has the `code` property. This is used to avoid `as` casting when you access the `code` property on errors returned by the module. #### Parameters | Parameter | Type | | --------- | ----- | | `error` | `any` | #### Returns `error is NativeModuleError` --- ### isNoSavedCredentialFoundResponse() > **isNoSavedCredentialFoundResponse**(`response`: [`OneTapResponse`](#onetapresponse)): `response is NoSavedCredentialFound` TypeScript helper to check if a response is a `noSavedCredentialFound` response. This is the same as checking if the `response.type === "noSavedCredentialFound"`. Use this if you prefer to use a function instead of comparing with a raw string. It supports both One Tap and Original Google Sign In responses. #### Parameters | Parameter | Type | | ---------- | ----------------------------------- | | `response` | [`OneTapResponse`](#onetapresponse) | #### Returns `response is NoSavedCredentialFound` #### Example ```ts const response = await GoogleOneTapSignIn.signIn(); if (isNoSavedCredentialFoundResponse(response)) { // the case when no user was previously signed in } ``` --- ### isSuccessResponse() > **isSuccessResponse**(`response`: [`OneTapResponse`](#onetapresponse)): `response is OneTapSuccessResponse` TypeScript helper to check if a response is a `cancelled` response. This is the same as checking if the `response.type === "cancelled"`. Use this if you prefer to use a function instead of comparing with a raw string. It supports both One Tap and Original Google Sign In responses. #### Parameters | Parameter | Type | | ---------- | ----------------------------------- | | `response` | [`OneTapResponse`](#onetapresponse) | #### Returns `response is OneTapSuccessResponse` #### Example ```ts const response = await GoogleOneTapSignIn.createAccount(); if (isSuccessResponse(response)) { // handle user signed in } ``` ## React Components ### GoogleLogoButtonProps > **GoogleLogoButtonProps** = \{ `label?`: `string`; `shape?`: `"rectangular"` \| `"circular"`; `textStyle?`: `StyleProp`\<`TextStyle`\>; `theme?`: `"light"` \| `"dark"` \| `"neutral"`; `variant?`: `"standard"` \| `"icon"`; \} #### Properties | Property | Type | Description | | ----------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------- | | `label?` | `string` | - | | `shape?` | `"rectangular"` \| `"circular"` | - | | `textStyle?` | `StyleProp`\<`TextStyle`\> | Style for the button text. Provide the Roboto font family with a weight of 500. | | `theme?` | `"light"` \| `"dark"` \| `"neutral"` | - | | `variant?` | `"standard"` \| `"icon"` | - | --- ### GoogleSigninButtonProps > **GoogleSigninButtonProps** = `ViewProps` & \{ `color?`: `"dark"` \| `"light"`; `disabled?`: `boolean`; `onPress?`: () => `void`; `size?`: `number`; \} #### Type Declaration | Name | Type | | ------------ | --------------------- | | `color?` | `"dark"` \| `"light"` | | `disabled?` | `boolean` | | `onPress()?` | () => `void` | | `size?` | `number` | --- ### WebGoogleSignInButtonProps > **WebGoogleSignInButtonProps** = `Omit`\<`GsiButtonConfiguration`, `"logo_alignment"`\> & \{ `logoAlignment?`: `GsiButtonConfiguration`\[`"logo_alignment"`\]; `onError?`: (`error`: `Error`) => `void`; \} #### Type Declaration | Name | Type | | ---------------- | ---------------------------------------------- | | `logoAlignment?` | `GsiButtonConfiguration`\[`"logo_alignment"`\] | | `onError()?` | (`error`: `Error`) => `void` | --- ### GoogleLogoButton > `const` **GoogleLogoButton**: `React.FC`\<`PressableProps` & [`GoogleLogoButtonProps`](#googlelogobuttonprops)\> Sign in button that follows the [Google branding guidelines](https://developers.google.com/identity/branding-guidelines). --- ### WebGoogleSigninButton > `const` **WebGoogleSigninButton**: `React.FC`\<[`WebGoogleSignInButtonProps`](#webgooglesigninbuttonprops)\> --- ### GoogleSigninButton() > **GoogleSigninButton**(`props`: [`GoogleSigninButtonProps`](#googlesigninbuttonprops)): `Element` Native Google Sign-In button component. Prefer using the [`GoogleLogoButton`](#googlelogobutton) for a more customizable button. #### Parameters | Parameter | Type | | --------- | ----------------------------------------------------- | | `props` | [`GoogleSigninButtonProps`](#googlesigninbuttonprops) | #### Returns `Element` ## Type Aliases ### CancelledResponse > **CancelledResponse** = \{ `data`: `null`; `type`: `"cancelled"`; \} The response object when the user cancels the flow for any operation that requires user interaction. On the web, this is also returned while [cooldown period](https://developers.google.com/identity/gsi/web/guides/features#exponential_cooldown) is active. Detecting the cooldown period itself is not possible on the web for user privacy reasons. On Android, it can be detected via `ONE_TAP_START_FAILED` #### Properties | Property | Type | | -------------------------- | ------------- | | `data` | `null` | | `type` | `"cancelled"` | --- ### ClientIdOrPlistPath > **ClientIdOrPlistPath** = \{ `iosClientId?`: `string`; \} \| \{ `googleServicePlistPath?`: `string`; \} iOS only. Configures the iOS client ID. By default, the iOS client ID is taken from the `GoogleService-Info.plist` Firebase config file (if present). You can specify a different bundle path for the config file, e.g. "GoogleService-Info-Staging". Alternatively, set the client ID explicitly by providing `iosClientId`. #### Type Declaration \{ `iosClientId?`: `string`; \} | Name | Type | Description | | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------ | | `iosClientId?` | `string` | If you want to specify the client ID of type iOS. It is taken from the `GoogleService-Info.plist` file by default. | \{ `googleServicePlistPath?`: `string`; \} | Name | Type | Description | | ------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `googleServicePlistPath?` | `string` | iOS only. Use this to specify a different bundle path name for the `GoogleService-Info` Firebase config file. **Example** `"GoogleService-Info-Staging"` | --- ### NoSavedCredentialFound > **NoSavedCredentialFound** = \{ `data`: `null`; `type`: `"noSavedCredentialFound"`; \} The response to calling One Tap's `signIn` and Original Google Sign In's `signInSilently` when no user was previously signed in, or they have since signed out or revoked access. #### Properties | Property | Type | | -------------------------- | -------------------------- | | `data` | `null` | | `type` | `"noSavedCredentialFound"` | ## Web Universal sign in module ### WebOneTapSignInCallbacks > **WebOneTapSignInCallbacks** = \{ `momentListener?`: `MomentListener`; `onError`: (`error`: `NativeModuleError`) => `void` \| `Promise`\<`void`\>; `onResponse`: (`userInfo`: [`OneTapExplicitSignInResponse`](#onetapexplicitsigninresponse)) => `void` \| `Promise`\<`void`\>; \} When using Universal sign in on the web, the sign in result is delivered via a callback, not via a promise. The shape of data delivered to the callback is the same as the shape of the data in the promise, enabling code reuse. Read more in the [guide](/docs/one-tap#web-support). #### Properties | Property | Type | Description | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `momentListener?` | `MomentListener` | A callback function that is called when important events take place. See [reference](https://developers.google.com/identity/gsi/web/reference/js-reference#PromptMomentNotification). | | `onError` | (`error`: `NativeModuleError`) => `void` \| `Promise`\<`void`\> | Called when an error occurs. You can use the `code` property of the error to determine the reason for the error. The reported errors on the web are in the same format as the errors reported on the native platforms, so you can reuse your error handling code. | | `onResponse` | (`userInfo`: [`OneTapExplicitSignInResponse`](#onetapexplicitsigninresponse)) => `void` \| `Promise`\<`void`\> | Called when the user successfully signs in, or cancels the sign in, either using the web One-tap flow or the button flow. | --- ## GoogleLogoButton A Google Sign-In button that follows Google's official branding guidelines. Intended for native apps. It renders null when used on the web. :::tip The functionality covered in this page is available in the licensed version. [You can get a license here](https://universal-sign-in.com/#pricing) ⭐️. ::: ## Features - Available in standard and icon-only variants - Customizable shape (rectangular or circular) - Supports light, dark, and neutral themes - Full customization possible via [Pressable props](https://reactnative.dev/docs/pressable#props) ## Usage See [API reference](/docs/api#googlelogobuttonprops) for props. ```tsx import { GoogleLogoButton } from '@react-native-google-signin/google-signin'; function SignInScreen() { return ( { // Handle sign in }} label="Sign in with Google" textStyle={{ fontFamily: 'Roboto' }} /> ); } ``` ## Font Requirements The button should render its label using the [Roboto font](https://fonts.google.com/specimen/Roboto) with weight of 500 to match Google's branding guidelines. Make sure to: 1. Include the Roboto font in your app (see [example for Expo](https://docs.expo.dev/versions/latest/sdk/font/#example-appjson-with-config-plugin)). 2. Provide the font family in the `textStyle` prop: ```tsx ``` --- ## WebGoogleSigninButton This is the sign-in button that you can use in web apps. It renders `null` when used in native apps. It has a slightly different API than the native `GoogleSigninButton` component which is why it exists as a separate component. :::tip The functionality covered in this page is available in the licensed version. [You can get a license here](https://universal-sign-in.com/#pricing) ⭐️. ::: The button will _not render_ before the [Google Client API has been loaded](../setting-up/web). You can use the `onError` prop to detect this case. ### Usage As the Universal sign in Guide explains, there are two ways to sign in on the web: using the One-tap UI or using the Google Sign-In button. One-tap UI may not always be available: This happens if user has [opted out](https://developers.google.com/identity/gsi/web/guides/features#globally_opt_out) or when they close the dialog several times in a row, entering the [cooldown period](https://developers.google.com/identity/gsi/web/guides/features#exponential_cooldown). The Google Sign-In button serves as a fallback. Tapping it opens the regular Google Sign-In dialog. ```tsx import { WebGoogleSigninButton } from '@react-native-google-signin/google-signin'; ; ``` ## Props All props are optional. | Name | Type | Description | | ---------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------- | | `type?` | `"standard"` \| `"icon"` | The type of the sign-in button. | | `theme?` | `"outline"` \| `"filled_blue"` \| `"filled_black"` | The theme of the sign-in button. | | `size?` | `"large"` \| `"medium"` \| `"small"` | The size of the sign-in button. | | `text?` | `"signin_with"` \| `"signup_with"` \| `"continue_with"` \| `"signin"` | The text to display on the sign-in button. | | `shape?` | `"rectangular"` \| `"pill"` \| `"circle"` \| `"square"` | The shape of the sign-in button. | | `width?` | `number` | The width of the sign-in button. | | `locale?` | `string` | The locale for the sign-in button. | | `logoAlignment?` | `"left"` \| `"center"` | The alignment of the logo on the button. | | `onError?` | `(error: Error) => void` | Called when you try to render the button before the Client SDK is loaded. | --- ## Configuration Doctor A command-line tool designed to help with Android signing configuration issues and quickly resolve the infamous `DEVELOPER_ERROR`, or potentially [other errors](#when-to-use) too. ## Why To save time. Developers sometimes waste hours or even days tracking down the [errors](#when-to-use). This tool gives you the SHA-1 fingerprints that need to be added to your Google project configuration to resolve the error. ## Usage The tool can extract SHA-1 fingerprints directly from a device/emulator with your app installed, or from an APK file. Run the command as shown below and follow the instructions. ```bash # Usage with device/emulator npx @react-native-google-signin/config-doctor --package-name com.yourapp.name # Usage with an APK file npx @react-native-google-signin/config-doctor --apk-path ./app-release.apk ``` ### Arguments - `--package-name` (optional): Your Android app's package name. If provided, the tool extracts the APK from a connected device/emulator. - `--apk-path` (optional): Path to an APK file. ## When to use When getting `DEVELOPER_ERROR`, unexpected [`cancelled`](https://issuetracker.google.com/issues/424210681) or even `GetCredentialProviderConfigurationException` during Sign-In. You can run into these errors: - When setting up Google Sign-In for the first time - After downloading your app from Play Store - When switching between debug and release builds ### Example Output ``` ✔ Application package name: com.some.app.android 🔍 Found the following SHA-1 certificate fingerprints: A1:B2:C3:D4:E5:F6:G7:H8:I9:J0:K1:L2:M3:N4:O5:P6:Q7:R8:S9:T0 Next steps: ... ``` ## Requirements - Active license (get access at [universal-sign-in.com](https://universal-sign-in.com)) - Android device/emulator with your app installed, OR a built APK file ## Related Documentation - [Collecting configuration information](./setting-up/get-config-file.mdx) --- ## Error handling When catching and handling errors thrown by the library, it's strongly recommended not to immediately present them using the [`Alert` module](https://reactnative.dev/docs/alert). This is because on Android, when transitioning from the Google Sign-In flow to your app, the current [Activity](https://developer.android.com/reference/android/app/Activity) may be `null` which would cause the alert call to be a noop. You can work around this by presenting the alert after a delay, or handling the error differently. ### `isErrorWithCode(value)` TypeScript helper to check if the passed parameter is an instance of `Error` which has the `code` property. All errors thrown by this library have the `code` property, which contains a value from [`statusCodes`](#status-codes) or some other string for the less-usual errors. `isErrorWithCode` can be used to avoid `as` casting when you want to access the `code` property on errors returned by the module. ```ts import { isErrorWithCode, GoogleSignin, } from '@react-native-google-signin/google-signin'; try { const userInfo = await GoogleSignin.signIn(); // do something with userInfo } catch (error) { if (isErrorWithCode(error)) { // here you can safely read `error.code` and TypeScript will know that it has a value } else { // this error does not have a `code`, and does not come from the Google Sign in module } } ``` ### Status Codes ```ts import { statusCodes } from '@react-native-google-signin/google-signin'; ``` Status codes are useful when determining which kind of error has occurred during the sign-in process. Under the hood, these constants are derived from native error codes and are platform-specific. Always compare `error.code` to `statusCodes.*` and do not rely on the raw value of `error.code`. See [example usage](one-tap#signin). | Name | Description | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `IN_PROGRESS` | Trying to invoke another operation (e.g. `signInSilently`) when previous one has not yet finished. If you call e.g. `signInSilently` twice, two calls to `signInSilently` in the native module are done. The promise from the first call to `signInSilently` will be rejected with this error, and the second will resolve / reject with the result of the native call. | | `PLAY_SERVICES_NOT_AVAILABLE` | Play services are not available or outdated. This happens on Android, or on the web when you're calling the exposed APIs [before the Client library is loaded](setting-up/web). | | `NULL_PRESENTER` | Happens in the unlikely situation when the `Activity` (on Android) or `UIViewController` (on iOS) for presenting the sign in UI isn't available. | ### Status codes specific to Universal sign in {#universal-status-codes} | Name | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `ONE_TAP_START_FAILED` | Thrown only on Android when the Universal sign in UI cannot be presented. This happens during the [cooldown period](https://developers.google.com/identity/gsi/web/guides/features#exponential_cooldown). You can still call `presentExplicitSignIn` in that case. | See [example usage](one-tap#signin). --- ## Installation There are two ways to consume the package: [paid](https://universal-sign-in.com) and free. If you are an EAS customer, you may be able to access the paid version for free, [learn more](https://forms.gle/tpP7TfUGW1CwgaEZ8). Why paid? According to the [State of React Native Survey](https://results.2024.stateofreactnative.com/en-US/opinions/#opinions_pain_points_multiple), unmaintained packages are **the #1 pain point** of the React Native ecosystem. Your purchase enables the module to be rock-solid, and contributions to upstream SDKs such as [1](https://github.com/openid/AppAuth-iOS/pull/788), [2](https://github.com/google/GoogleSignIn-iOS/pull/402), [3](https://github.com/googlesamples/google-services/issues/426), [4](https://github.com/google/GoogleSignIn-iOS/issues/457), [5](https://issuetracker.google.com/issues/424210681), [6](https://issuetracker.google.com/issues/474817166). [//]: # '🌟' ### Universal Sign In (premium) {#premium} ⭐️ **Key Features**: - **Cross-Platform**: Unified APIs which work on **Android**, **iOS**, **Web**, and **macOS**. - Android: Built with [Credential Manager library](https://developers.google.com/identity/android-credential-manager) - Web: Uses [Sign In with Google for Web](https://developers.google.com/identity/gsi/web/guides/features) - iOS & macOS: Powered by the [Google Sign-In SDK](https://developers.google.com/identity/sign-in/ios/start) - **Licensed:** see [pricing](https://universal-sign-in.com/#pricing) and [license](https://universal-sign-in.com/license). - **Trusted**: A total of over 750k npm package downloads. - **Faster Sign-Ups**: Reduce sign-up and sign-in times on Android by up to 50%, according to [Google](https://developer.android.com/identity/sign-in/legacy-gsi-migration#authentication). - **See the UI**: [screenshots](screenshots) of the features. - **Widely compatible & stable:** Both old and [new architecture](https://reactnative.dev/architecture/landing-page) of React Native are supported. See version [compatibility table](#requirements) below. 🔧 **Easier setup**: - Android [Config Doctor](/docs/config-doctor) that might save you from pulling your hair out. - Automatic detection of [configuration parameters](one-tap#automatic-config) for faster integration. 🛡️ **Advanced [security features](/docs/security)** [//]: # '🖥️ **Unified API** - Write code once, deploy everywhere.' 📱 **An example app** — to showcase all features on native and web ### Public version (free) Available on the public npm registry, this version: - Uses the functional, but deprecated [legacy Android Google Sign-In](https://web.archive.org/web/20240308064911/https://developers.google.com/identity/sign-in/android/start-integrating). The free package will continue to use a version where the deprecated but functional SDK is present. - Has platform support limited to Android and iOS. - Contains none of the extra features listed above. > To migrate from the public version to the premium one, follow the [migration guide](migrating#migrating-from-original-to-universal-sign-in). ## Accessing the private npm package {#package-manager-setup} The private npm package is like any other, but it's hosted on the [GitHub npm packages registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry), not the public npm registry. Therefore, a small bit of setup is needed: 1. [Obtain here](https://github.com/settings/tokens/new?description=react-native-google-sign-in&scopes=read:packages) a Personal Access Token with `packages:read` permission and set expiration to "No expiration". 2. Set up your package manager to fetch the package from the GH packages registry. In this example, we're using an `NPM_TOKEN_GOOGLE_SIGN_IN` environment variable. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; create a `.yarnrc.yml` file in your project root with the following content: ```yml title=".yarnrc.yml" npmScopes: react-native-google-signin: npmRegistryServer: https://npm.pkg.github.com npmAuthToken: '${NPM_TOKEN_GOOGLE_SIGN_IN}' ``` create a `.npmrc` file in your project root with the following content: ```txt title=".npmrc" //npm.pkg.github.com/:_authToken=${NPM_TOKEN_GOOGLE_SIGN_IN} @react-native-google-signin:registry=https://npm.pkg.github.com/ ``` CI environment setup is similar to the local one: you also need a `.npmrc` (or similar) file. Follow [this GitHub Actions example](https://gist.github.com/nandorojo/46b3e46de12177b9ad7e4d454310de21#file-private-npm-in-gh-actions-md) - other CI providers require very similar steps. If you use another package manager ([such as Bun](https://bun.sh/docs/install/registries)), refer to its documentation for setting up a custom registry. ## Installing ```bash yarn add @react-native-google-signin/google-signin@latest ``` ```bash npm i @react-native-google-signin/google-signin@latest ``` After installing: if you're using the Universal version, open the lockfile (`yarn.lock` / `package-lock.json`...) and verify that the package is fetched from the GitHub registry (the entry must point to `npm.pkg.github.com`, not `registry.npmjs.org`). If it does not, it means the package manager is not configured correctly — try uninstalling and reinstalling the package. There are several guides to follow now: - [Expo guide](setting-up/expo) for native mobile apps built with Expo - [Web guide](setting-up/web) if you want to use the package on web - If you're not using Expo but plain React Native, follow [Android guide](setting-up/android) and [iOS guide](setting-up/ios) ## Requirements For latest version of Universal Sign In, `compileSdkVersion` must be {'>='} 35 and `kotlinVersion` must be {'>='} 2.0.21 in your Android project. If you use Expo SDK 53 or newer, these requirements are already met. Use [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/#example-appjson-with-config-plugin) to specify these values on Expo SDK {'<='} 52. The latest version of the Universal Sign In package supports (use older versions of the package if you run older React Native / Expo): | | supported range | | ------------ | --------------- | | expo | 52.0.40 - 54 | | react-native | 0.76.0 - 0.83 | --- ## Migration guides There are 2 migrations described here: from Original to Universal Sign In and from the old JS API to the new JS API. ## Migrating from Original to Universal Sign In Migrating from Original to Universal module is mostly about changing the method names: the table summarizes the mapping from Original module's calls to the Universal (OneTap) module's calls: | Original Method | Universal (OneTap) Method | Notes | | ------------------------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `configure` | `configure` | Same functionality. | | `signInSilently` | `signIn` | Universal's `signIn` attempts sign in without user interaction. | | `signIn` | `createAccount` | Universal's `createAccount` is for first-time sign in (but can be used for existing users too). | | `addScopes` | `requestAuthorization` | Similar functionality, different parameters. On Android, you can call `requestAuthorization` without being signed in! | | `hasPlayServices` | `checkPlayServices` | Same functionality, different name. | | `getCurrentUser` | Use `signIn` response | Manage the current user state yourself, or through libraries like [Firebase Auth](https://rnfirebase.io/auth/usage#listening-to-authentication-state) or [Supabase Auth](https://supabase.com/docs/reference/javascript/auth-onauthstatechange). | | `getTokens` | Use `signIn` or `requestAuthorization` | Tokens are included in the response object. | | `signOut` | `signOut` | | | `revokeAccess` | `revokeAccess` | Universal requires email/id parameter on web. | | `hasPreviousSignIn` | Use `signIn` response | Check for `noSavedCredentialFound` response type. | | `clearCachedAccessToken` | `clearCachedAccessToken` | Same functionality. | --- ## Migrating to the new JS API Version 13 introduced a new JS API, which changes some method response signatures and makes minor changes to error handling (details [here](https://github.com/react-native-google-signin/google-signin/pull/1326)). If you're upgrading from version 12 or earlier, you'll need to make some minor adjustments. ### Universal Sign In 1. Add the [`configure`](one-tap#configure) method to your code. This method is required to be called to configure the module. 2. Change the `signIn`, `createAccount`, `presentExplicitSignIn`, and `requestAuthorization` methods to use the new apis: That means that the data you previously accessed directly on `userInfo` (see below - for example `userInfo.name`) will now be nested in `userInfo.data` (e.g. `userInfo.data.name`). See [`OneTapResponse` type](/docs/api#onetapresponse): ```diff const signIn = async () => { try { - const userInfo = await GoogleOneTapSignIn.signIn({ - webClientId: `autoDetect`, // works only if you use Firebase - iosClientId: config.iosClientId, // only needed if you're not using Firebase - }); - setState({ userInfo }); // use e.g. `userInfo.name` + const response = await GoogleOneTapSignIn.signIn(); + + if (response.type === 'success') { + setState({ userInfo: response.data }); + } else if (response.type === 'noSavedCredentialFound') { + // Android and Apple only. No saved credential found, call `createAccount` + } } catch (error) { if (isErrorWithCode(error)) { switch (error.code) { - case statusCodes.NO_SAVED_CREDENTIAL_FOUND: - // Android and Apple only. No saved credential found, call `createAccount` - break; - case statusCodes.SIGN_IN_CANCELLED: - // sign in was cancelled - break; case statusCodes.ONE_TAP_START_FAILED: // Android-only, you probably have hit rate limiting. // On Android, you can still call `presentExplicitSignIn` in this case. break; case statusCodes.PLAY_SERVICES_NOT_AVAILABLE: // Android-only: play services not available or outdated // Web: when calling an unimplemented api (requestAuthorization) break; default: // something else happened } } else { // an error that's not related to google sign in occurred } } }; ``` 3. If requesting offline access in `requestAuthorization` on Android, add `enabled: true`: ```diff await GoogleOneTapSignIn.requestAuthorization({ offlineAccess: { + enabled: true, }, }); ``` ### Original Sign In 1. Follow step 2. from above for `signIn`, `addScopes` and `signInSilently` methods. 2. remove `SIGN_IN_REQUIRED` mentions. This case is now handled with [`NoSavedCredentialFound`](api#nosavedcredentialfound) object: ```diff const getCurrentUserInfo = async () => { try { const response = await GoogleSignin.signInSilently(); + if (isSuccessResponse(response)) { + setState({ userInfo: response.data }) + } else if (isNoSavedCredentialFoundResponse(response)) { + // user has not signed in yet + } - setState({ userInfo: response }); } catch (error) { - if (error.code === statusCodes.SIGN_IN_REQUIRED) { - // user has not signed in yet - } else { - // some other error - } } }; ``` --- ## 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](#web-support)). It is a replacement for the [Original Google sign in](original). The module APIs are named `GoogleOneTapSignIn` for historical reasons. :::tip The functionality covered in this page is available in the licensed version. [You can get a license here](https://universal-sign-in.com/#pricing) ⭐️. ::: - On Android, it is built on top of the new [Credential Manager](https://developers.google.com/identity/android-credential-manager) APIs. - On Apple (iOS and macOS), it is built on top of the [Google Sign In SDK for iOS and macOS](https://developers.google.com/identity/sign-in/ios/start-integrating). - On the web, it covers both the [One-tap](https://developers.google.com/identity/gsi/web/guides/offerings#one_tap) flow and the [Google Sign-In button](https://developers.google.com/identity/gsi/web/guides/offerings#sign_in_with_google_button). [Learn more](web-support). ## Usage You can copy-paste this snippet to get a complete sign-in flow quickly. Read more about the methods below. ```tsx title="example of going through the sign in flow" showLineNumbers import { GoogleOneTapSignIn, GoogleLogoButton, } from '@react-native-google-signin/google-signin'; ; const startSignInFlow = async () => { try { GoogleOneTapSignIn.configure(); // move this to after your app starts await GoogleOneTapSignIn.checkPlayServices(); const signInResponse = await GoogleOneTapSignIn.signIn(); if (signInResponse.type === 'success') { // use signInResponse.data } else if (signInResponse.type === 'noSavedCredentialFound') { // the user wasn't previously signed into this app const createResponse = await GoogleOneTapSignIn.createAccount(); if (createResponse.type === 'success') { // use createResponse.data } else if (createResponse.type === 'noSavedCredentialFound') { // no Google user account was present on the device yet (unlikely but possible) const explicitResponse = await GoogleOneTapSignIn.presentExplicitSignIn(); if (explicitResponse.type === 'success') { // use explicitResponse.data } } } // the else branches correspond to the user canceling the sign in } catch (error) { // handle error } }; ``` Note that on Apple and Android, you can combine the Universal sign in methods with those one from the [Original Google Sign In](original). 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. --- ## Methods ### `configure` signature: (`params`: [`OneTapConfigureParams`](api#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](#automatic-config). If you're using neither Expo nor Firebase, you also need to provide the `iosClientId` parameter. All other parameters are optional. ```ts title="Example of calling the configure() method" GoogleOneTapSignIn.configure({ webClientId: 'autoDetect', }); ``` --- ### `signIn` signature: (`params`?: [`OneTapSignInParams`](api#onetapsigninparams)) => `Promise`\<[`OneTapResponse`](api#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](https://developers.google.com/identity/sign-in/ios/reference/Classes/GIDSignIn#-restoreprevioussigninwithcompletion:). | | Web | Attempts to sign in user automatically, without interaction. [Docs](https://developers.google.com/identity/gsi/web/reference/js-reference#auto_select). If none is found, presents a sign-in UI. [Read below](#web-support) for web support. | If there is no user that was previously signed in, the returned promise resolves with [`NoSavedCredentialFound`](api#nosavedcredentialfound) object. In that case, you can call [`createAccount`](one-tap#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 | 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 ```ts title="Example of calling the signIn() method" showLineNumbers 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`](errors#iserrorwithcodevalue) for processing errors - [`isSuccessResponse`](api#issuccessresponse) for checking if a response represents a successful operation. Same as checking `response.type === 'success'`. - [`isNoSavedCredentialFoundResponse`](api#isnosavedcredentialfoundresponse) for checking if a response represents no saved credentials case. Same as checking `response.type === 'noSavedCredentialFound'`. - [`isCancelledResponse`](api#iscancelledresponse) for checking if a response represents user cancellation case. Same as checking `response.type === 'cancelled'`. --- ### `createAccount` signature: (`params`?: [`OneTapCreateAccountParams`](api#onetapcreateaccountparams)) => `Promise`\<[`OneTapResponse`](api#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](https://developers.google.com/identity/sign-in/ios/reference/Classes/GIDSignIn#-signinwithpresentingviewcontroller:hint:completion:). 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](#web-support) 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](api#nosavedcredentialfound), as indicated in the code snippet above.
UI screenshots | Android | iOS | Web | | :------------------------------------------------------------------------: | :--------------------------------------------------------------------: | :--------------------------------------------------------------------: | | | | |
```ts await GoogleOneTapSignIn.createAccount(); ``` --- ### `presentExplicitSignIn` signature: (`params`?: [`OneTapExplicitSignInParams`](api#onetapexplicitsigninparams)) => `Promise`\<[`OneTapExplicitSignInResponse`](api#onetapexplicitsigninresponse)\> | Platform | Behavior | | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Android | Presents the sign in dialog explicitly. This is useful when the user has hit rate limiting ([`ONE_TAP_START_FAILED`](errors#universal-status-codes)) and the one-tap flow is thus not available, or if both `signIn` and `createAccount` resolve with [`NoSavedCredentialFound`](api#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](buttons/google-logo-button).
UI screenshots | Android | iOS | Web | | :----------------------------------------------------------------------: | :--------------------------------------------------------------------: | :--------------------------------------------------------------------: | | | | |
```ts await GoogleOneTapSignIn.presentExplicitSignIn(); ``` --- ### `checkPlayServices` signature: (`showErrorResolutionDialog`?: `boolean`): `Promise`\<[`PlayServicesInfo`](api#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](#example-code-snippet)). 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 ![prompt install](/img/prompt-install.png) ![prompt enable](/img/prompt-enable.png)
- 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](setting-up/web), rejects otherwise. ```ts title="Example of checkPlayServices() method" await GoogleOneTapSignIn.checkPlayServices(); ``` --- ### `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. ```ts await GoogleOneTapSignIn.signOut(); ``` --- ### `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. ```ts await GoogleOneTapSignIn.revokeAccess(user.id); ``` --- ### `requestAuthorization` signature: (`params`: [`RequestAuthorizationParams`](api#requestauthorizationparams)) => `Promise`\<[`AuthorizationResponse`](api#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](https://developers.google.com/android/reference/com/google/android/gms/auth/api/identity/AuthorizationRequest.Builder). | | Apple | Calls [`addScopes`](./original.mdx#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 | | :-----------------------------------------------------------------------: | :--------------------------------------------------------------------: | | | |
--- ### `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](https://developers.google.com/identity/sign-in/ios/reference/Classes/GIDGoogleUser#-refreshtokensifneededwithcompletion:)). ## Automatic `webClientId` & `iosClientId` detection {#automatic-config} 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: ```xml WEB_CLIENT_ID your-web-client-id.apps.googleusercontent.com ``` 2. 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 [Learn more](web-support). --- ## Advanced security :::tip The functionality covered in this page is available in the licensed version. [You can get a license here](https://universal-sign-in.com/#pricing) ⭐️. ::: # Advanced security There are 2 security-related features available: 1. [Custom nonce (on all platforms)](#custom-nonce) 2. [App Check for iOS](#appcheck) ## Custom nonce [Nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) (number used once) is a security measure used to mitigate replay attacks and to associate a Client session with an ID Token. The authorization APIs in [Universal Sign-In](/docs/one-tap) for Apple, Android and web allow you to specify nonce. Example usage: ```ts const response = await GoogleOneTapSignIn.createAccount({ nonce: getUrlSafeNonce(), }); ``` `getUrlSafeNonce()` generates a URL-safe nonce. It can be implemented using `expo-crypto` or `react-native-get-random-values`: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; [//]: # 'or use uuid v4 with react-native-get-random-values or expo-crypto' ```ts import * as Crypto from 'expo-crypto'; export function getUrlSafeNonce(byteLength = 32) { if (byteLength < 1) { throw new Error('Byte length must be positive'); } const randomBytes = Crypto.getRandomValues(new Uint8Array(byteLength)); return btoa(String.fromCharCode(...randomBytes)) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/[=]/g, ''); } ``` ```ts import 'react-native-get-random-values'; export function getUrlSafeNonce(byteLength = 32) { if (byteLength < 1) { throw new Error('Byte length must be positive'); } const randomBytes = crypto.getRandomValues(new Uint8Array(byteLength)); return btoa(String.fromCharCode(...randomBytes)) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/[=]/g, ''); } ``` ### Usage with Supabase Auth providers such as [Supabase](https://supabase.com/docs/reference/javascript/auth-signinwithidtoken) require passing SHA-256 hash (digest) of the nonce ([source](https://github.com/supabase/auth-js/blob/dfb40d24188f7e8b0d34e51ded15582086250c51/src/lib/types.ts#L612)). This can be done as follows: ```ts import { digestStringAsync, CryptoDigestAlgorithm } from 'expo-crypto'; export const getNonce = async () => { // `rawNonce` goes to Supabase's signInWithIdToken(). // Supabase makes a hash of `rawNonce` and compares it with the `nonceDigest` // which is included in the ID token from RN-google-signin. const rawNonce = getUrlSafeNonce(); // `nonceDigest` (SHA-256 hash, hex-encoded) goes to the `nonce` parameter in RN-google-signin APIs const nonceDigest = await digestStringAsync( CryptoDigestAlgorithm.SHA256, rawNonce, ); return { rawNonce, nonceDigest }; }; ``` ```ts import QuickCrypto from 'react-native-quick-crypto'; const getNonce = () => { // `rawNonce` goes to Supabase's signInWithIdToken(). // Supabase makes a hash of `rawNonce` and compares it with the `nonceDigest` // which is included in the ID token from RN-google-signin. const rawNonce = getUrlSafeNonce(); // `nonceDigest` (SHA-256 hash, hex-encoded) goes to the `nonce` parameter in RN-google-signin APIs const nonceDigest = QuickCrypto.createHash('sha256') .update(rawNonce) .digest('hex'); return { rawNonce, nonceDigest }; }; ``` ## App Check for iOS (advanced) {#appcheck} App Check helps protect your apps from abuse by preventing unauthorized clients from authenticating using Google Sign-in: only the apps you've authorized can acquire access tokens and ID tokens from Google's OAuth 2.0 and OpenID Connect endpoint. [Read more about App Check](https://developers.google.com/identity/sign-in/ios/appcheck) to understand it. ### Setup To set up App Check: 1. Set up Google API Console / Firebase console by following ["1. Set up your project"](https://developers.google.com/identity/sign-in/ios/appcheck/get-started#project-setup). Do not follow step 2. 2. Add **App Attest** capability to your app (as in [here](https://developers.google.com/identity/sign-in/ios/appcheck/get-started#install-sdk)). If you're using Expo, the capability can be added according to the [iOS capabilities documentation](https://docs.expo.dev/build-reference/ios-capabilities/). 3. (skip if you use Expo): Ensure that `GIDClientID` (the iOS client ID) is set in your `Info.plist`. Expo config plugin does this for you. ### Usage Call `GoogleOneTapSignIn.enableAppCheck()` as shown below. Do this early, before invoking any authentication apis. The call either resolves when it succeeds or rejects with an error. On platforms other than iOS, the method is a no-op and resolves. ```ts await GoogleOneTapSignIn.enableAppCheck(); ``` Use `APP_CHECK_API_KEY` [env variable in Xcode](https://stackoverflow.com/a/76212610/2070942) to configure the [debug provider](https://developers.google.com/identity/sign-in/ios/appcheck/debug-provider) with the API key. Then call: ```ts await GoogleOneTapSignIn.enableAppCheck(); ``` :::danger API keys and debug tokens are sensitive data. Keep them private. ::: Configure the [debug provider](https://developers.google.com/identity/sign-in/ios/appcheck/debug-provider) with the API key: ```ts await GoogleOneTapSignIn.enableAppCheck({ debugProviderAPIKey: config.apiKey, }); ``` :::danger API keys and debug tokens are sensitive data. Keep them private. ::: ### Enable App Check enforcement Read the [official documentation](https://developers.google.com/identity/sign-in/ios/appcheck/enable-enforcement) to understand how to enforce App Check. --- ## Android setup guide :::warning If you use Expo, follow [this guide](/setting-up/expo.md) instead. This guide applies to vanilla React Native apps only. ::: ## Google project configuration - Follow [this](./get-config-file) guide to set up your project and get the configuration information which you'll need later. ### Without Firebase Authentication You don't need to do any more modifications. ### With Firebase Authentication #### 1. Download the configuration file - Download the configuration file (`google-services.json`) from Firebase. Then, place it into your project according to [these instructions](https://developers.google.com/android/guides/google-services-plugin#adding_the_json_file). #### 2. Update gradle files Update `android/build.gradle` with ```groovy title="android/build.gradle" buildscript { // ... dependencies { // highlight-start classpath 'com.google.gms:google-services:4.4.0' // <--- use this version or newer // highlight-end } } ``` Update `android/app/build.gradle` with ```groovy title="android/app/build.gradle" apply plugin: "com.android.application" apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" // highlight-next-line apply plugin: 'com.google.gms.google-services' ``` This ends the setup for Firebase. ## Rebuild the native project Do not forget to rebuild the native app after the setup is done. --- ## Expo setup ## Prepare your Expo project :::note This package cannot be used in [Expo Go](https://docs.expo.dev/workflow/overview/#expo-go-an-optional-tool-for-learning) because it uses native code. This applies to both the [Original](../original) and [Universal](../one-tap) modules. However, you can add custom native code to an Expo app by using a [development build](https://docs.expo.dev/workflow/overview/#development-builds). That is the recommended approach for production apps, and is documented in this guide. ::: ## Add config plugin After installing the npm package, add a config plugin (read more details below) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`. There are 2 config plugins available: for projects with Firebase, and without Firebase. ### Expo without Firebase If you're _not_ using Firebase, provide the `iosUrlScheme` option to the config plugin. To obtain `iosUrlScheme`, follow [these instructions](./get-config-file?firebase-or-not=cloud-console#ios). ```json title="app.json | js" { "expo": { "plugins": [ [ "@react-native-google-signin/google-signin", { "iosUrlScheme": "com.googleusercontent.apps._some_id_here_" } ] ] } } ``` ### Expo and Firebase Authentication If you are using Firebase Authentication, follow [these instructions](./get-config-file?firebase-or-not=firebase#step-2) to get `google-services.json` file for Android and [these instructions](./get-config-file?firebase-or-not=firebase#ios)) to get `GoogleService-Info.plist` for iOS. Place them into your project and specify the paths to the files: ```json title="app.json | js" { "expo": { "plugins": ["@react-native-google-signin/google-signin"], "android": { "googleServicesFile": "./google-services.json" }, "ios": { "googleServicesFile": "./GoogleService-Info.plist" } } } ``` ## Build the native app Run the following to generate the native project directories. ```sh npx expo prebuild --clean ``` Rebuild your app and read the [config guide](./get-config-file)! ```sh npx expo run:android && npx expo run:ios ``` --- ## Collecting configuration information Before getting your hands dirty with code, some configuration needs to be taken care of. Configuration information collected in this guide is used in later steps of the setup and in the `configure()` call: [1](/docs/one-tap#configure) or [2](/docs/original#configure). You **do not** need to use Firebase to configure Google Sign In. ## Android Follow the two steps below to set up Google Sign In for your Android app. :::warning In case you encounter any of the following issues, revisit this guide - it means the steps below weren't fully completed. - if you ever get the infamous `DEVELOPER_ERROR` error - if you can sign in with debug APK and not in release (or vice versa) ::: ### Step 1: Collect SHA-1 (not SHA-256) certificate fingerprints Your Android app probably uses multiple signing configurations. For example, an app might be signed differently when building `debug` and `release` APKs locally or when building on [Expo EAS](https://docs.expo.dev/app-signing/managed-credentials/#inspecting-credentials-configuration). Then there's the [Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en) for store deployments — Google Play Store may _re-sign_ your app using one of its own signing configurations. :::important If your app is not yet in the Play Store, focus only on the development APK and its SHA-1 certificate fingerprint. You can come back to this guide later when you upload your app to the Play Store. However, be advised that in the end, you need to get the SHA-1 certificate fingerprints for _all_ signing configurations and then use _all_ of those SHA-1 fingerprints in [Step 2](#step-2) below. ::: #### Collect SHA-1 certificate fingerprints from: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Use the [Configuration Doctor](../config-doctor.md). (Requires an [Universal sign in](/docs/install#premium) license.) 1. Get a device / emulator with the app installed, or get the APK (build it locally or in cloud, download from the Play Console / Play Store...) 2. Run the tool and follow its instructions: ```bash npx @react-native-google-signin/config-doctor ``` Check if "Google Play App Signing" is enabled for your app [in the console](https://play.google.com/console/). If it is enabled, you need to take the following steps: 1. In Google Play Console, navigate to: \ -> Release section (in the left sidebar) -> Setup -> App Signing. 2. Under the "App signing key certificate", take note of `SHA-1 certificate fingerprint`(s). Play Store sometimes has more than one "App signing key certificate"! If you use [Expo EAS](https://expo.dev/eas), run `eas credentials` to obtain the Keystore information, which includes the SHA-1 fingerprint. See [EAS credentials docs](https://docs.expo.dev/app-signing/managed-credentials/#inspecting-credentials-configuration) to learn more. 1. From your project root, `cd android && ./gradlew signingReport`. 2. Scroll to the top of output, see the fingerprints. Debug fingerprint is used for locally-built debug APK, release fingerprint is used for release APK. ### Step 2: Add SHA-1 fingerprints to Firebase or Google Cloud Console {#step-2} Using _all_ of the SHA-1 fingerprints obtained in the previous step, follow the instructions below. 1. Sign in to [Firebase Console](https://console.firebase.google.com/) and open your project. 2. Ensure that in the "Authentication" menu, "Google" is enabled as "Sign-in method". 3. Click the settings icon and go to "Project settings". 4. Scroll down to "Your apps" section, and select the app. 5. Click "Add fingerprint". 6. Check that "Package name" is correct. 7. Download the `google-services.json` file. ![Firebase, add Android keystore's SHA-1 to your project](/img/android-fingerprint-firebase.png) Create an OAuth Client ID of type Android in [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_) for each of the SHA-1 fingerprints you obtained - see the screenshot below. Alternatively, use this wizard. You will _NOT_ need the created IDs later - the only goal here is for them to be created in the Google Cloud Console. ![Google Cloud Console - creating Android OAuth ID](/img/android-client-id.png) --- ## iOS Read below on how to set up Google Sign In for your iOS app. 1. Sign in to [Firebase Console](https://console.firebase.google.com/) and open your project. 2. Ensure that in the "Authentication" menu, "Google" is enabled as "Sign-in method". 3. Click the settings icon and go to "Project settings". 4. Scroll down to "Your apps" section, and select the app. 5. Check that "Bundle ID" is correct. 6. Download the `GoogleService-Info.plist` file. Remember that _all_ created client IDs can be found in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_). Obtain the "iOS OAuth Client ID" _and_ "iOS URL scheme" (also known as `reversed client id`): Create an OAuth Client ID of type iOS in [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_) as seen in the screenshot below. Alternatively, use this wizard. You will need the iOS Client ID and iOS URL scheme later. ![Google Cloud Console - creating iOS OAuth ID](/img/ios-client-id.png) --- ## Web Client ID [//]: # '(offline support, web support)' To get a Web Client ID (for the `configure()` call), go to [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_) and find an existing one (it may have been already created by Firebase) or create a new OAuth Client ID of type **Web**. --- ## Summary At the end of this guide, regardless of whether you use Firebase, when you visit [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_), you should have in the "OAuth 2.0 Client IDs" section: - Android OAuth Client ID(s) with SHA-1 fingerprints - iOS OAuth Client ID(s) with iOS URL scheme - Web Client ID --- ## iOS setup guide :::warning If you use Expo, follow [this guide](/setting-up/expo.md) instead. This guide applies to vanilla React Native apps only. ::: ### Link the native module - run `pod install` in the `ios/` directory to install the module ### Google project configuration - Follow [this](./get-config-file) guide to get the configuration information which you need for the next steps. ### Firebase Authentication If you're using Firebase Authentication, download the `GoogleService-Info.plist` file and place it into your Xcode project. ### Xcode configuration - Configure URL types in the `Info` panel (see screenshot) - add your "iOS URL scheme" (also known as `reversed client id`), which can be found in [Google Cloud Console](https://console.cloud.google.com/apis/credentials?project=_) under your iOS client ID. - If you need to support Mac Catalyst, you need to enable the Keychain Sharing capability on each build target. No keychain groups need to be added. ![link config](/img/urlTypes.png) ## Rebuild the native project Do not forget to rebuild the native app after the setup is done. ### Optional: modify your app to respond to the URL scheme This is only required if you have multiple listeners for `openURL` - for instance if you have both Google and Facebook OAuth. Because only one `openURL` method can be defined, if you have multiple listeners for `openURL`, you must combine them into a single function as shown below: #### For AppDelegate written in Swift If your AppDelegate a Swift file (the default in React Native 0.77.0 or higher), you'll need to: 1. Add the following import to your project's [bridging header](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift#Import-Code-Within-an-App-Target) file (usually `ios/YourProject-Bridging-Header.h`): ```objc // … // ⬇️ Add this import #import ``` 2. Modify your `AppDelegate.swift` file: ```swift // … @main class AppDelegate: RCTAppDelegate { // … // ⬇️ Add this method override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { // Add any other URL handlers you're using (e.g. Facebook SDK) return ApplicationDelegate.shared.application(app, open: url, options: options) || GIDSignIn.sharedInstance.handle(url) } } ``` #### For AppDelegate written in Objective-C For AppDelegate written in Objective-C (the default prior to React Native 0.77), modify your `AppDelegate.m` file: ```objc #import "AppDelegate.h" #import // ⬅️ add the header import // … @implementation AppDelegate // … // ⬇️ Add this method before file @end - (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary *)options { // Add any other URL handlers you're using (e.g. Facebook SDK) return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options] || [GIDSignIn.sharedInstance handleURL:url]; } @end ``` --- ## Web setup guide The web implementation doesn't depend on React Native (or React Native Web). That means you can use it even with regular web apps created with NextJS, Vite and etc. :::tip The functionality covered in this page is available in the licensed version. [You can get a license here](https://universal-sign-in.com/#pricing) ⭐️. ::: On the web, you need to load the Google Client Library and make it available in the browser **before** calling any of the APIs exposed by this package. There are different ways to load the client script. Some of them are: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ```tsx import Script from 'next/script';