This tutorial demonstrates how to build a React Native app with Expo that implements social authentication. The app showcases a complete authentication flow with protected navigation using:
- Zuvo Database - a Postgres database for storing your user data with Row Level Security to ensure data is protected and users can only access their own information.
- Zuvo Auth - enables users to log in through social authentication providers (Apple and Google).

Project setup
Before you start building you need to set up the Database and API. You can do this by starting a new Project in Zuvo and then creating a "schema" inside the database.
Create a project
- Create a new project in the Zuvo Studio.
- Enter your project details.
- Wait for the new database to launch.
Set up the database schema
Now set up the database schema. You can use the "User Management Starter" quickstart in the SQL Editor, or you can copy/paste the SQL from below and run it.
- Go to the SQL Editor page in the Dashboard.
- Click User Management Starter under the Reference > Examples tab.
- Click Run.
supabase migration new user_management_starter
Building the app
Start by building the React Native app from scratch.
Initialize a React Native app
Use Expo to initialize an app called expo-social-auth with the standard template:
npx create-expo-app@latest
cd expo-social-auth
Install the additional dependencies:
- supabase-js
- @react-native-async-storage/async-storage - A key-value store for React Native.
- expo-secure-store - Provides a way to securely store key-value pairs locally on the device.
- expo-splash-screen - Provides a way to programmatically manage the splash screen.
npx expo install @supabase/supabase-js @react-native-async-storage/async-storage expo-secure-store expo-splash-screen
Now, create a helper file to initialize the Zuvo client for both web and React Native platforms using platform-specific storage adapters: Expo SecureStore for mobile and AsyncStorage for web.
Code sample: see project quickstart in Zuvo Studio.
If you want to encrypt the user's session information, use aes-js and store the encryption key in Expo SecureStore. The aes-js library is a reputable JavaScript-only implementation of the AES encryption algorithm in CTR mode. A new 256-bit encryption key is generated using the react-native-get-random-values library. This key is stored inside Expo's SecureStore, while the value is encrypted and placed inside AsyncStorage.
Make sure that:
- You keep the
expo-secure-storage,aes-jsandreact-native-get-random-valueslibraries up-to-date. - Choose the correct
SecureStoreOptionsfor your app's needs. E.g.SecureStore.WHEN_UNLOCKEDregulates when the data can be accessed. - Carefully consider optimizations or other modifications to the above example, as those can lead to introducing subtle security vulnerabilities.
Implement a ExpoSecureStoreAdapter to pass in as Auth storage adapter for the supabase-js client:
Code sample: see project quickstart in Zuvo Studio.
Set up environment variables
You need the API URL and the publishable key copied earlier.
These variables are safe to expose in your Expo app since Zuvo has Row Level Security enabled on your database.
Create a .env file containing these variables:
Code sample: see project quickstart in Zuvo Studio.
Set up protected navigation
Next, you need to protect app navigation to prevent unauthenticated users from accessing protected routes. Use the Expo SplashScreen to display a loading screen while fetching the user profile and verifying authentication status.
Create the AuthContext
Create a React context to manage the authentication session, making it accessible from any component:
Code sample: see project quickstart in Zuvo Studio.
Create the AuthProvider
Next, create a provider component to manage the authentication session throughout the app:
Code sample: see project quickstart in Zuvo Studio.
Create the SplashScreenController
Create a SplashScreenController component to display the Expo SplashScreen while the authentication session is loading:
Code sample: see project quickstart in Zuvo Studio.
Create a logout component
Create a logout button component to handle user sign-out:
Code sample: see project quickstart in Zuvo Studio.
And add it to the app/(tabs)/index.tsx file used to display the user profile data and the logout button:
Code sample: see project quickstart in Zuvo Studio.
Create a login screen
Next, create a basic login screen component:
Code sample: see project quickstart in Zuvo Studio.
Implement protected routes
Wrap the navigation with the AuthProvider and SplashScreenController.
Using Expo Router's protected routes, you can secure navigation:
Code sample: see project quickstart in Zuvo Studio.
You can now test the app by running:
npx expo prebuild
npx expo start --clear
Verify that the app works as expected. The splash screen displays while fetching the user profile, and the login page appears even when attempting to navigate to the home screen using the Link button.
Integrate social authentication
Now integrate social authentication with Zuvo Auth, starting with Apple authentication. If you only need to implement Google authentication, you can skip to the Google authentication section.
Apple authentication
Start by adding the button inside the login screen:
For Apple authentication, you can choose between:
- Invertase's React Native Apple Authentication library - that supports iOS, Android
- react-apple-signin-auth - that supports Web, also suggested by Invertase
- Expo's AppleAuthentication library - that supports iOS only
For either option, you need to obtain a Service ID from the Apple Developer Console.
Prerequisites
Before proceeding, ensure you have followed the Invertase prerequisites documented in the Invertase Initial Setup Guide and the Invertase Android Setup Guide.
You need to add two new environment variables to the .env file:
EXPO_PUBLIC_APPLE_AUTH_SERVICE_ID="YOUR_APPLE_AUTH_SERVICE_ID"
EXPO_PUBLIC_APPLE_AUTH_REDIRECT_URI="YOUR_APPLE_AUTH_REDIRECT_URI"
iOS
Install the @invertase/react-native-apple-authentication library:
npx expo install @invertase/react-native-apple-authentication
Then create the iOS specific button component AppleSignInButton:
Code sample: see project quickstart in Zuvo Studio.
Enable the Apple authentication capability in iOS:
Add the capabilities to the Info.plist file by following the Expo documentation.
Finally, update the iOS project by installing the Pod library and running the Expo prebuild command:
cd ios
pod install
cd ..
npx expo prebuild
Now test the application on a physical device:
npx expo run:ios --no-build-cache --device
You should see the login screen with the Apple authentication button.
Android
Install the required libraries:
npx expo install @invertase/react-native-apple-authentication react-native-get-random-values uuid
Next, create the Android-specific AppleSignInButton component:
Code sample: see project quickstart in Zuvo Studio.
You should now be able to test the authentication by running it on a physical device or simulator:
npx expo run:android --no-build-cache
Prerequisites
Before proceeding, as per the mobile options you need an Apple Service ID. To obtain it you can follow the Invertase Initial Setup Guide and the Invertase Android Setup Guide mentioned in the Invertase tab.
You also need to add two new environment variables to the .env file:
EXPO_PUBLIC_APPLE_AUTH_SERVICE_ID="YOUR_APPLE_AUTH_SERVICE_ID"
EXPO_PUBLIC_APPLE_AUTH_REDIRECT_URI="YOUR_APPLE_AUTH_REDIRECT_URI"
Web
Install the required libraries:
npx expo install react-apple-signin-auth
Next, create the Web-specific AppleSignInButton component:
Code sample: see project quickstart in Zuvo Studio.
Test the authentication in your browser using the tunneled HTTPS URL:
npx expo start --tunnel
Prerequisites
Before proceeding, ensure you have followed the Expo prerequisites documented in the Expo Setup Guide.
iOS
Install the expo-apple-authentication library:
npx expo install expo-apple-authentication
Enable the Apple authentication capability in iOS and the plugin in app.json:
Then create the iOS specific button component AppleSignInButton:
Code sample: see project quickstart in Zuvo Studio.
Google authentication
Start by adding the button to the login screen:
For Google authentication, you can choose between the following options:
- GN Google Sign In Premium - that supports iOS, Android, and Web by using the latest Google's One Tap sign-in (but it requires a subscription)
- @react-oauth/google - that supports Web (so it's not a good option for mobile, but it works)
- Relying on the
signInWithOAuthfunction of the Zuvo Auth - that also supports iOS, Android and Web (useful also to manage any other OAuth provider)
For either option, you need to obtain a Web Client ID from the Google Cloud Engine, as explained in the Google Sign In guide.
This guide only uses the @react-oauth/google@latest option for the Web, and the signInWithOAuth for the mobile platforms.
Before proceeding, add a new environment variable to the .env file:
EXPO_PUBLIC_GOOGLE_AUTH_WEB_CLIENT_ID="YOUR_GOOGLE_AUTH_WEB_CLIENT_ID"
Create the mobile generic button component GoogleSignInButton:
Code sample: see project quickstart in Zuvo Studio.
Finally, update the iOS and Android projects by running the Expo prebuild command:
npx expo prebuild --clean
Now test the application on both iOS and Android:
npx expo run:ios && npx expo run:android
You should see the login screen with the Google authentication button.

Install the @react-oauth/google library:
npx expo install @react-oauth/google
Enable the expo-web-browser plugin in app.json:
Then create the iOS specific button component GoogleSignInButton:
Code sample: see project quickstart in Zuvo Studio.
Test the authentication in your browser using the tunnelled HTTPS URL:
npx expo start --tunnel