High-performance Universal (One Tap) Google Sign-In for React Native, powered by Nitro Modules.
📘 Documentation: react-native-nitro-google-sign-in.github.io (source: docs/ submodule → docs repo)
| Guide | Link |
|---|---|
| npm package | react-native-nitro-google-signin |
| Installation & native linking | Installation |
| Quick start | Quick Start |
| Google Cloud & config files | Setup |
| API reference | API reference |
| Troubleshooting | Troubleshooting |
🤖 AI agents: install the skill — npx skills add react-native-nitro-google-sign-in/google-signin -g -y · docs · list on skills.sh
- Android: Credential Manager + Google ID (
GetGoogleIdOption/GetSignInWithGoogleOption) - iOS: Google Sign-In SDK for iOS (
restorePreviousSignIn, interactivesignIn)
- React Native ≥ 0.76
react-native-nitro-modules(required peer dependency)
Install both this package and react-native-nitro-modules:
Bun
bun add react-native-nitro-google-signin react-native-nitro-modulesYarn
yarn add react-native-nitro-google-signin react-native-nitro-modulesnpm
npm install react-native-nitro-google-signin react-native-nitro-modulesAutolinking handles Android and iOS. From your app project root, install CocoaPods dependencies:
bundle exec pod install --project-directory="ios"Run bundle install once first if your app has a Gemfile. Rebuild the native app after install — Metro alone is not enough.
Full steps: Installation guide.
This library uses native code (Nitro + Google Sign-In SDK). It does not run in Expo Go; use a development build.
Add the plugin to app.json or app.config.js, then run npx expo prebuild.
With Firebase / Google Services files (recommended for webClientId: 'autoDetect'):
{
"expo": {
"plugins": ["react-native-nitro-google-signin"],
"android": {
"googleServicesFile": "./google-services.json"
},
"ios": {
"googleServicesFile": "./GoogleService-Info.plist"
}
}
}The plugin applies the Google Services Gradle plugin on Android (generates default_web_client_id), copies GoogleService-Info.plist into the iOS target, and adds the reversed client ID URL scheme from REVERSED_CLIENT_ID in the plist.
You can also pass file paths via plugin options instead of top-level expo.android / expo.ios:
{
"expo": {
"plugins": [
[
"react-native-nitro-google-signin",
{
"iosGoogleServicesFile": "./GoogleService-Info.plist",
"androidGoogleServicesFile": "./google-services.json"
}
]
]
}
}Without Firebase (manual iOS URL scheme only):
{
"expo": {
"plugins": [
[
"react-native-nitro-google-signin",
{
"iosUrlScheme": "com.googleusercontent.apps.YOUR_IOS_CLIENT_ID"
}
]
]
}
}Use the REVERSED_CLIENT_ID value from the Google Cloud Console iOS OAuth client (or from GoogleService-Info.plist). On Android without google-services.json, pass an explicit webClientId in configure() instead of 'autoDetect'.
npx expo prebuild --clean
npx expo run:ios
npx expo run:androidSee Expo setup for the full guide.
- Create OAuth clients in Google Cloud Console: Web, Android, and iOS.
- Android: add your app SHA-1 and package name; apply the Google Services plugin so
default_web_client_idis generated, or passwebClientIdexplicitly. - iOS: add
GoogleService-Info.plist, URL scheme (REVERSED_CLIENT_ID), and optionallyWEB_CLIENT_IDforwebClientId: 'autoDetect'.
Step-by-step: Google Cloud & config files · Android · iOS.
Same flow as the Usage guide and Quick Start:
import {
GoogleOneTapSignIn,
isNoSavedCredentialFoundResponse,
isSuccessResponse,
} from 'react-native-nitro-google-signin'
GoogleOneTapSignIn.configure({ webClientId: 'autoDetect' })
const startSignInFlow = async () => {
await GoogleOneTapSignIn.checkPlayServices()
let response = await GoogleOneTapSignIn.signIn()
if (isNoSavedCredentialFoundResponse(response)) {
response = await GoogleOneTapSignIn.createAccount()
}
if (isNoSavedCredentialFoundResponse(response)) {
response = await GoogleOneTapSignIn.presentExplicitSignIn()
}
if (isSuccessResponse(response)) {
const { user, idToken } = response.data
// send idToken to your backend
}
}You can request Google API access in two ways. Use full scope URLs (not short names like calendar).
| Approach | When to use |
|---|---|
configure({ scopes }) |
You know which scopes you need before the user signs in (consent may appear during sign-in). |
requestScopes() |
You need extra permissions after sign-in (e.g. user taps “Connect calendar” on a settings screen). |
Request scopes up front. Set offlineAccess: true if your backend needs a serverAuthCode to exchange for refresh tokens:
import {
GoogleOneTapSignIn,
isNoSavedCredentialFoundResponse,
isSuccessResponse,
} from 'react-native-nitro-google-signin'
const CALENDAR_READONLY = 'https://www.googleapis.com/auth/calendar.readonly'
GoogleOneTapSignIn.configure({
webClientId: 'autoDetect',
scopes: [CALENDAR_READONLY],
offlineAccess: true,
})
const signInWithScopesUpFront = async () => {
await GoogleOneTapSignIn.checkPlayServices()
let response = await GoogleOneTapSignIn.signIn()
if (isNoSavedCredentialFoundResponse(response)) {
response = await GoogleOneTapSignIn.createAccount()
}
if (isSuccessResponse(response)) {
const { user, idToken, serverAuthCode } = response.data
// idToken — authenticate the user
// serverAuthCode — send to your backend when offlineAccess is true
console.log(user.email, idToken, serverAuthCode)
}
}Start with basic sign-in, then request more access when the user needs a feature:
import {
GoogleOneTapSignIn,
isSuccessResponse,
} from 'react-native-nitro-google-signin'
const CALENDAR_READONLY = 'https://www.googleapis.com/auth/calendar.readonly'
GoogleOneTapSignIn.configure({ webClientId: 'autoDetect' })
// 1) Sign in first (basic profile / idToken only)
const signInThenRequestScopes = async () => {
await GoogleOneTapSignIn.checkPlayServices()
const response = await GoogleOneTapSignIn.signIn()
if (!isSuccessResponse(response)) return
const { user, idToken } = response.data
// user is signed in — app works without calendar access
// 2) Later: user taps “Enable calendar” (or similar)
await enableCalendarAccess()
}
const enableCalendarAccess = async () => {
const { serverAuthCode } = await GoogleOneTapSignIn.requestScopes([
CALENDAR_READONLY,
])
// User may see a consent screen; exchange serverAuthCode on your backend
if (serverAuthCode) {
await fetch('/api/google/exchange-code', {
method: 'POST',
body: JSON.stringify({ serverAuthCode }),
})
}
}requestScopes() requires an active signed-in session. See Usage — OAuth scopes · API reference — requestScopes.
Live demos: example/App.tsx and example-expo/App.tsx (requestAdditionalScopes).
| Method | Description |
|---|---|
configure(params) |
Required before other calls. webClientId or 'autoDetect'; optional scopes, offlineAccess, hostedDomain, nonce, autoSelectOnSignIn. |
checkPlayServices() |
Android: validates Play Services. iOS: no-op resolve. |
signIn() |
Silent / restore previous sign-in. |
createAccount() |
Interactive account picker (sign-up). |
presentExplicitSignIn() |
Explicit Sign in with Google UI. |
requestScopes(scopes) |
Request additional OAuth access after sign-in; returns { serverAuthCode }. |
signOut() |
Clears local Google session (iOS SDK); disable auto sign-in on Android. |
revokeAccess(id) |
Disconnect app (iOS); no-op token revoke on Android CredMan. |
Also exported: native GoogleSignInButton, useGoogleSignInFromButton, response helpers (isSuccessResponse, isNoSavedCredentialFoundResponse, isCancelledResponse, isErrorWithCode), and statusCodes.
Full types and parameters: API reference.
| App | Description |
|---|---|
example/ |
Bare React Native app (includes requestScopes demo) |
example-expo/ |
Expo dev-client app (config plugin + autoDetect) |
Configure Firebase / GoogleService-Info.plist and google-services.json before testing on device. See example-expo/README.md for Expo prebuild steps.
- Contributing — development setup and PR guidelines (docs site)
- Code of Conduct
- Security policy
- Support
- Documentation — Community
Contributors: keep sign-in flows and API docs aligned with the Usage guide and API reference.
MIT