Back to Tutorials

Google Sign-In with Expo and Firebase

Add native Google authentication to iOS and Android with Firebase Auth, Android Credential Manager, an Expo development build, and the signing credentials your production release actually uses.

August 8, 2026 16 min read Paddy B
ExpoReact NativeGoogle Sign-InFirebase AuthCredential Manager

The working architecture in 2026

Use react-native-nitro-google-signin to get a Google ID token, turn that token into a Firebase credential with GoogleAuthProvider.credential(), then call signInWithCredential(). The library uses Credential Manager on Android and the native Google Sign-In SDK on iOS.

This distinction matters because Firebase Authentication does not display a native Google account picker for you. Google performs the identity step; Firebase accepts the resulting ID token and creates or restores the Firebase user session.

Google has deprecated the legacy Google Sign-In SDK on Android and recommends Credential Manager for new integrations. The older public @react-native-google-signin/google-signin API is still widespread, but its free Android implementation uses that legacy stack. This guide follows the current free Credential Manager path.

This does not work in Expo Go

Google Sign-In needs native modules and native configuration. Install expo-dev-client, add the config plugin, and rebuild the app. Restarting Metro cannot add native code to an existing Expo Go binary.

Before you start

You need an Expo app with unique native identifiers and an existing Firebase project. If Firebase Auth itself is new to your app, start with the Firebase Auth in Expo production setup, then return here for the Google provider.

{ "expo": { "name": "My App", "slug": "my-app", "android": { "package": "com.example.myapp" }, "ios": { "bundleIdentifier": "com.example.myapp" } } }

Treat the package name and bundle identifier as permanent once the app ships. The identifiers in Expo, Firebase, Google OAuth clients, and the store listing must match exactly.

1. Enable Google in Firebase Auth

  1. Open Firebase Console and select your project.
  2. Go to Authentication → Sign-in method.
  3. Enable Google, choose a support email, and save.
  4. In Project settings → Your apps, register one Android app and one iOS app using the identifiers from your Expo config.

Also complete the Google Auth Platform branding and audience settings for the Cloud project behind Firebase. While the app is in testing, only configured test users may be able to sign in. Before launch, confirm the consent screen, support email, privacy-policy URL, and requested scopes are ready for production.

2. Register every Android SHA-1

Android validates both the package name and the certificate that signed the installed app. That means one app can need several SHA-1 fingerprints:

  • Your local debug certificate for npx expo run:android.
  • The certificate used for EAS development, preview, or production builds.
  • The Google Play App Signing certificate used for downloads from the Play Store.

For a local debug keystore, run:

keytool -list -v \ -keystore ~/.android/debug.keystore \ -alias androiddebugkey \ -storepass android \ -keypass android

Add the reported SHA-1 under Firebase Project settings → Your apps → Android app. For EAS-managed credentials, inspect the Android credentials with eas credentials -p android. For a Play release, copy the SHA-1 shown under Play Console → Release → Setup → App integrity → App signing key certificate.

The classic production-only failure

If the account picker works in a local build but the Play Store build fails, the Play App Signing SHA-1 is usually missing. The upload key and Play app-signing key are different certificates; registering only the upload key is not enough.

3. Download both Firebase config files

After registering the native apps, enabling Google, and adding Android fingerprints, download fresh copies of:

  • google-services.json for Android.
  • GoogleService-Info.plist for iOS.

Place both files at the project root. The Android file must match expo.android.package; the iOS file must match expo.ios.bundleIdentifier. The generated files also provide the Web OAuth client ID used to mint a Google ID token Firebase can accept. On iOS, the plist supplies the reversed client ID used for the return URL scheme.

These Firebase client configuration files identify your app and project; they are not equivalent to a service-account private key. You can commit them, or store them as EAS file variables if that better suits your repository policy. Never put an Admin SDK service account in the mobile app.

4. Install the native packages

npx expo install expo-dev-client react-native-nitro-modules react-native-nitro-google-signin

This adds the development client, the Nitro runtime, and the Google Sign-In bridge. You still keep the Firebase JS SDK already used by the rest of the app:

npx expo install firebase @react-native-async-storage/async-storage

You do not need React Native Firebase merely to exchange the Google token. The modular Firebase JS API exposes the same GoogleAuthProvider and signInWithCredential operations needed here.

5. Add the Expo config plugin

Update app.json so Expo copies the Firebase files, applies the Android Google Services plugin, and registers the iOS URL scheme:

{ "expo": { "android": { "package": "com.example.myapp", "googleServicesFile": "./google-services.json" }, "ios": { "bundleIdentifier": "com.example.myapp", "googleServicesFile": "./GoogleService-Info.plist" }, "plugins": [ "react-native-nitro-google-signin" ] } }

When those file paths are present, the plugin can auto-detect the Web client ID and register REVERSED_CLIENT_ID for iOS. You should not need manual Gradle changes.

6. Build a development client

Native configuration is applied at build time. Generate and run local native projects:

npx expo prebuild --clean npx expo run:ios npx expo run:android

Or create a shareable development build with EAS:

eas build --profile development --platform all

If you change a plugin, native identifier, Firebase file, or signing credential, rebuild the binary. A JavaScript refresh is enough only for JavaScript changes. The EAS Build and Submit checklist covers build profiles and store delivery in more detail.

7. Configure Google and exchange the ID token

Configure the native library once near app startup. With the Firebase files wired through the config plugin, autoDetect reads the correct Web OAuth client ID on both platforms.

import { GoogleOneTapSignIn } from "react-native-nitro-google-signin"; GoogleOneTapSignIn.configure({ webClientId: "autoDetect", });

Then create a small auth service. The first call looks for an authorized credential, the next offers account creation, and the final fallback displays an explicit sign-in flow.

import { GoogleOneTapSignIn, isNoSavedCredentialFoundResponse, isSuccessResponse, } from "react-native-nitro-google-signin"; import { GoogleAuthProvider, signInWithCredential, } from "firebase/auth"; import { Platform } from "react-native"; import { auth } from "./firebase"; export async function signInWithGoogle() { if (Platform.OS === "android") { 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)) { return null; } const idToken = response.data?.idToken; if (!idToken) { throw new Error("Google Sign-In returned no ID token"); } const credential = GoogleAuthProvider.credential(idToken); return signInWithCredential(auth, credential); }

The Google ID token is short-lived proof of identity. Firebase validates it and returns a normal Firebase UserCredential. Your existing onAuthStateChanged provider and Expo Router protection can treat Google users exactly like email/password users.

8. Connect a sign-in button

Keep the screen responsible for loading state and friendly errors; keep the provider exchange in the service.

import { useState } from "react"; import { Alert, Button, View } from "react-native"; import { signInWithGoogle } from "../lib/google-auth"; export function GoogleSignInButton() { const [loading, setLoading] = useState(false); async function handlePress() { try { setLoading(true); await signInWithGoogle(); } catch (error) { console.error(error); Alert.alert( "Could not sign in", "Check your connection and try again." ); } finally { setLoading(false); } } return ( <View> <Button title={loading ? "Signing in…" : "Continue with Google"} disabled={loading} onPress={handlePress} /> </View> ); }

Use Google's approved button wording and visual guidelines in the finished UI. Do not interpret a user closing the account picker as a broken account; cancellation should normally leave the person on the same screen without an alarming error.

9. Sign out of both layers

Firebase owns the app session, while the native Google library remembers Google authorization. Clear both when the user explicitly signs out:

import { GoogleOneTapSignIn } from "react-native-nitro-google-signin"; import { signOut } from "firebase/auth"; import { auth } from "./firebase"; export async function signOutEverywhere() { await signOut(auth); await GoogleOneTapSignIn.signOut(); }

Signing out is not the same as deleting an account or revoking access. If the user chooses account deletion, delete your application data, revoke provider access where appropriate, and then delete the Firebase user. Reauthentication may be required for that sensitive operation.

Troubleshooting Google Sign-In in Expo

“Native module” or Nitro module not found

You are running in Expo Go or in a development client built before the package was installed. Run prebuild and rebuild the native app.

DEVELOPER_ERROR on Android

The installed binary's package name or signing certificate does not match an Android OAuth client. Check the package in google-services.json, add the exact SHA-1 to Firebase, download the file again, and rebuild.

default_web_client_id is missing

The Android Firebase file is absent, points to a different package, or was not processed by the Google Services Gradle plugin. Confirm android.googleServicesFile and the config plugin, then prebuild cleanly.

iOS opens Google but never returns to the app

Confirm the plist contains REVERSED_CLIENT_ID and that the generated iOS app has that URL scheme. If the redirect still stalls or the app has multiple URL handlers, follow the library's AppDelegate forwarding instructions.

It works from EAS but not Google Play

Add the Play App Signing SHA-1, not only the EAS/upload certificate. Re-download google-services.json after changing Firebase settings, then ship a new build.

The Android emulator shows no Google accounts

Use an emulator system image that includes Google APIs or Google Play, sign into a Google account on the emulator, and make sure Play Services is current.

Production checklist

  • Google provider enabled in Firebase Authentication.
  • Google Auth Platform branding, audience, test users, and privacy links configured.
  • Expo package name and bundle identifier exactly match Firebase.
  • Local, EAS/upload, and Play App Signing SHA-1 fingerprints registered.
  • Fresh Android JSON and iOS plist included in each EAS build environment.
  • Development build tested on a real iPhone and an Android device with Play Services.
  • Play-distributed build tested after Play App Signing changes the certificate.
  • Sign-in cancellation, offline errors, sign-out, reauthentication, and account deletion handled.
  • Firestore and Storage authorization still based on Firebase request.auth.uid.

If your Firebase files differ by environment, pair this setup with the EAS environment variables guide for Firebase and Expo.

Frequently asked questions

Does Google Sign-In work in Expo Go?

No. The required native code is not included in Expo Go. Use an Expo development build or a production build.

Why does Google Sign-In work locally but fail from Google Play?

Google Play App Signing signs store downloads with a different certificate. Add its SHA-1 fingerprint to Firebase, download an updated Android config file, and rebuild.

Should a new Expo app use Android Credential Manager?

Yes. Google recommends Credential Manager for new Android sign-in integrations. This setup uses it on Android while keeping the native Google Sign-In SDK on iOS.