react-native-google-auth
Version:
🚀 Modern React Native Google Authentication library with TypeScript support. Features latest Google Sign-In SDK, OAuth 2.0, One Tap Sign-In, token management, and cross-platform iOS/Android integration. Perfect for implementing Google Login, Google SSO,
1,238 lines (1,001 loc) • 39.4 kB
Markdown
# React Native Google Authentication Library | Modern Google Sign-In SDK
[](https://badge.fury.io/js/react-native-google-auth)
[](https://img.shields.io/npm/d18m/react-native-google-auth.svg)
[](https://github.com/sbaiahmed1/react-native-google-auth/stargazers)
> ⚠️ **Development Status**: This library is currently in active development. While core functionality is implemented and working, some features may still be under development or subject to change. Please use with caution in production environments.
**react-native-google-auth** is a comprehensive React Native Google Authentication library that provides seamless Google Sign-In integration for iOS and Android applications. Built with modern APIs including Google Sign-In SDK for iOS and Android Credential Manager, this library offers the most up-to-date Google authentication solution for React Native developers.
## Why Choose react-native-google-auth?
This React Native Google Sign-In library stands out from other Google authentication solutions by leveraging the latest Google APIs and providing a unified, type-safe interface for both iOS and Android platforms. Perfect for developers looking to implement Google OAuth, Google Login, or Google SSO in their React Native mobile applications.
## Key Features & Benefits
### 🚀 Modern Google Authentication APIs
- ✅ **Latest Google Sign-In SDK**: Uses Google Sign-In SDK for iOS and Android Credential Manager (not deprecated GoogleSignIn)
- ✅ **Google One Tap Sign-In**: Seamless authentication experience with saved credentials
- ✅ **OAuth 2.0 Compliant**: Full OAuth 2.0 and OpenID Connect support
- ✅ **Token Management**: Automatic token refresh and expiration handling
### 💻 Developer Experience
- ✅ **Full TypeScript Support**: Complete TypeScript definitions and IntelliSense
- ✅ **Cross-Platform Compatibility**: Works seamlessly on both iOS and Android
- ✅ **Zero Configuration**: Minimal setup required with sensible defaults
- ✅ **Comprehensive Documentation**: Detailed guides and API reference
### 🔒 Security & Reliability
- ✅ **Secure Token Storage**: Secure credential storage using platform keychain
- ✅ **Error Handling**: Comprehensive error codes and user-friendly messages
- ✅ **Production Ready**: Battle-tested authentication flows
- ✅ **Google Play Services**: Automatic Google Play Services availability checking
### 🍎 iOS Configuration Improvements (New!)
- ✅ **Automatic Client ID Detection**: Reads client ID from Info.plist when not provided
- ✅ **Configuration Validation**: Comprehensive validation for all configuration parameters
- ✅ **Enhanced Scope Management**: Support for additional OAuth scopes beyond default
- ✅ **Better Error Handling**: Detailed error messages for missing or invalid configuration
### 🤖 Android Configuration Improvements (New!)
- ✅ **Automatic Client ID Detection**: Reads client ID from google-services.json when not provided
- ✅ **Configuration Validation**: Comprehensive validation for all configuration parameters
- ✅ **Enhanced Scope Management**: Support for additional OAuth scopes beyond default
- ✅ **Better Error Handling**: Detailed error messages for missing or invalid configuration
### 🎯 Use Cases
- **React Native Google Login**: Implement Google sign-in in React Native apps
- **Mobile OAuth Authentication**: Secure user authentication for mobile apps
- **Social Login Integration**: Add Google as a social login provider
- **Enterprise SSO**: Single Sign-On for enterprise applications
- **User Profile Management**: Access Google user profile information
## Installation & Setup Guide
### NPM Installation
Install the React Native Google Authentication library using your preferred package manager:
```bash
# Using Yarn (Recommended)
yarn add react-native-google-auth
# Using NPM
npm install react-native-google-auth
# Using pnpm
pnpm add react-native-google-auth
```
### Quick Start
Get started with Google Sign-In in your React Native app in just 3 steps:
1. **Install the package** (see above)
2. **Configure your Google OAuth credentials** (see setup guides below)
3. **Initialize and use** the authentication methods
```typescript
import { GoogleAuth, GoogleAuthScopes } from 'react-native-google-auth';
// Configure once in your app
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID',
androidClientId: 'YOUR_ANDROID_CLIENT_ID',
scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE]
});
// Sign in users
const response = await GoogleAuth.signIn();
```
### iOS Setup
1. Install pods:
```bash
cd ios && pod install
```
*Note: The GoogleSignIn dependency is automatically included via the library's podspec.*
2. **Configure Client ID (Choose one method):**
**Method A: Automatic Detection from Info.plist (Recommended)**
Add your iOS client ID to `ios/Info.plist`:
```xml
<key>GIDClientID</key>
<string>YOUR_IOS_CLIENT_ID</string>
```
With this method, you can configure without providing `iosClientId`:
```typescript
await GoogleAuth.configure({
androidClientId: 'YOUR_ANDROID_CLIENT_ID'
// iosClientId automatically detected from Info.plist
});
```
**Method B: Manual Configuration**
Provide the client ID directly in your configuration:
```typescript
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID',
androidClientId: 'YOUR_ANDROID_CLIENT_ID'
});
```
**Method C: GoogleService-Info.plist (Alternative)**
If you have a `GoogleService-Info.plist` file, the library will automatically detect the `CLIENT_ID` from it.
3. Add URL schemes to `ios/Info.plist` (replace with your actual iOS client ID):
```xml
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>googleauth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_IOS_CLIENT_ID</string>
</array>
</dict>
</array>
```
**Note:** Remove `.apps.googleusercontent.com` from your iOS client ID when adding it to URL schemes.
4. Configure URL handling in your `AppDelegate.swift`:
```swift
import GoogleSignIn
// Add this method to handle URL schemes
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return GIDSignIn.sharedInstance.handle(url)
}
```
### Android Setup
1. Add the following to your `android/app/build.gradle`:
```gradle
dependencies {
implementation 'androidx.credentials:credentials:1.3.0'
implementation 'androidx.credentials:credentials-play-services-auth:1.3.0'
implementation 'com.google.android.libraries.identity.googleid:googleid:1.1.0'
}
```
*Note: These dependencies are automatically included via the library's build.gradle.*
2. **Configure Client ID (Choose one method):**
**Method A: Automatic Detection from google-services.json (Recommended)**
Add your `google-services.json` file to `android/app/` directory:
```
android/
└── app/
└── google-services.json
```
With this method, you can configure without providing `androidClientId`:
```typescript
await GoogleAuth.configure({
androidClientId: 'YOUR_ANDROID_CLIENT_ID',
// androidClientId automatically detected from google-services.json
});
```
**Method B: Manual Configuration**
Provide the client ID directly in your configuration:
```typescript
await GoogleAuth.configure({
androidClientId: 'YOUR_ANDROID_CLIENT_ID',
iosClientId: 'YOUR_IOS_CLIENT_ID'
});
```
### Expo Setup (Development Build)
> **Note**: This library requires native code and is **not compatible with Expo Go**. You must use Expo Development Build or eject to a bare React Native project.
#### Prerequisites
- Expo SDK 49+ (recommended)
- Expo Development Build configured
#### Installation
1. **Install the package:**
```bash
npx expo install react-native-google-auth
```
2. **Configure the plugin in your `app.json` or `app.config.js`:**
The library automatically detects client IDs from your Google configuration files. You have several options:
**Option 1: Automatic Detection (Recommended)**
Place your Google configuration files in your project root:
- `google-services.json` (Android)
- `GoogleService-Info.plist` (iOS)
Add the plugin to your `app.json`:
```json
{
"expo": {
"plugins": [
"react-native-google-auth"
]
}
}
```
Then configure without specifying client IDs:
```javascript
await GoogleAuth.configure({
scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE]
});
```
**Option 2: Manual Configuration**
```javascript
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID',
androidClientId: 'YOUR_ANDROID_CLIENT_ID',
scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE]
});
```
**Option 3: Environment Variables in app.config.js**
```javascript
export default {
expo: {
plugins: [
'react-native-google-auth'
]
}
};
```
Then use environment variables in your code:
```javascript
await GoogleAuth.configure({
iosClientId: process.env.GOOGLE_IOS_CLIENT_ID,
androidClientId: process.env.GOOGLE_ANDROID_CLIENT_ID,
scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE]
});
```
#### iOS Configuration
1. **Add your iOS client ID to `app.json`:**
```json
{
"expo": {
"ios": {
"infoPlist": {
"GIDClientID": "YOUR_IOS_CLIENT_ID"
},
"bundleIdentifier": "com.yourcompany.yourapp"
}
}
}
```
2. **Configure URL schemes in `app.json`:**
```json
{
"expo": {
"ios": {
"scheme": "com.googleusercontent.apps.YOUR_IOS_CLIENT_ID"
}
}
}
```
**Note:** Remove `.apps.googleusercontent.com` from your iOS client ID when adding it as a scheme.
#### Android Configuration
1. **Add your `google-services.json` file:**
- Download `google-services.json` from Firebase Console
- Place it in your project root (same level as `app.json`)
- The config plugin will automatically copy it to the correct location
2. **Configure package name in `app.json`:**
```json
{
"expo": {
"android": {
"package": "com.yourcompany.yourapp"
}
}
}
```
#### Building Development Build
1. **Create a development build:**
```bash
# For iOS
eas build --profile development --platform ios
# For Android
eas build --profile development --platform android
# For both platforms
eas build --profile development --platform all
```
2. **Install the development build on your device**
3. **Start the development server:**
```bash
npx expo start --dev-client
```
#### Usage in Expo
```typescript
import { GoogleAuth, GoogleAuthScopes } from 'react-native-google-auth';
import { useEffect } from 'react';
export default function App() {
useEffect(() => {
configureGoogleAuth();
}, []);
const configureGoogleAuth = async () => {
try {
await GoogleAuth.configure({
// Client IDs are automatically detected from app.json configuration
scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE]
});
} catch (error) {
console.error('Google Auth configuration failed:', error);
}
};
const handleGoogleSignIn = async () => {
try {
const response = await GoogleAuth.signIn();
if (response.type === 'success') {
console.log('User signed in:', response.data.user);
} else if (response.type === 'cancelled') {
console.log('Sign in cancelled');
}
} catch (error) {
console.error('Sign in failed:', error);
}
};
// Your app components...
}
```
#### Expo Config Plugin Options
The config plugin accepts the following options:
```typescript
interface GoogleAuthPluginOptions {
iosClientId?: string; // iOS OAuth client ID
androidClientId?: string; // Android OAuth client ID
googleServicesFile?: string; // Path to google-services.json (default: './google-services.json')
}
```
#### Troubleshooting Expo Issues
**Common Issues:**
1. **"Google Auth not configured" in Expo:**
- Ensure you've added the config plugin to `app.json`
- Rebuild your development build after adding the plugin
- Verify client IDs are correctly set in the plugin configuration
2. **"Invalid client ID" in Expo:**
- Check that your bundle identifier (iOS) and package name (Android) match your Google Cloud Console configuration
- Ensure you're using the correct client IDs for your platform
3. **Build fails with Google Auth:**
- Make sure you're using Expo SDK 49+
- Clear your build cache: `eas build --clear-cache`
- Verify `google-services.json` is in the project root
4. **Sign-in doesn't work in development build:**
- Ensure you're testing on a physical device (not Expo Go)
- Check that Google Play Services are installed and updated (Android)
- Verify your app's SHA-1 fingerprint is added to Google Cloud Console (Android)
**Getting SHA-1 fingerprint for Expo:**
```bash
# For development builds
eas credentials -p android
# Or manually from keystore
keytool -list -v -keystore path/to/your/keystore.jks -alias your-key-alias
```
#### Expo Limitations
- **Expo Go**: Not supported - requires development build
- **Web**: Not supported - mobile platforms only
- **Expo Router**: Fully compatible with file-based routing
- **Expo Updates**: Compatible with OTA updates
## Getting Client IDs
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing one
3. Enable **Google Sign-In API**
4. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client IDs**
### For iOS:
- Application type: **iOS**
- Bundle ID: Your iOS app's bundle identifier
- Copy the **Client ID**
### For Android:
- Application type: **Android**
- Package name: Your Android app's package name
- SHA-1 certificate fingerprint:
```bash
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
```
- Copy the **Client ID**
## Usage
### Import
```typescript
import { GoogleAuth, GoogleAuthScopes } from 'react-native-google-auth';
```
### Configure (Required - Call this first)
```typescript
const configure = async () => {
try {
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID', // Optional on iOS - auto-detected from Info.plist
androidClientId: 'YOUR_ANDROID_CLIENT_ID', // Preferred for Android
webClientId: 'YOUR_WEB_CLIENT_ID', // Fallback for Android, required for server verification
hostedDomain: 'yourdomain.com', // Optional - for G Suite domains
scopes: [ // Optional - additional OAuth scopes (use enum for common scopes)
GoogleAuthScopes.EMAIL,
GoogleAuthScopes.PROFILE,
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/calendar.readonly'
]
});
console.log('Google Auth configured successfully');
} catch (error) {
console.error('Configuration failed:', error);
}
};
```
#### Configuration Options
- **iosClientId** (iOS): Optional if configured in Info.plist. The library automatically detects from:
1. `GIDClientID` key in Info.plist (recommended)
2. `CLIENT_ID` key in GoogleService-Info.plist
- **androidClientId** (Android): Optional if google-services.json is configured. The library automatically detects from:
1. `google-services.json` file in android/app/ directory (recommended)
2. Falls back to webClientId if neither androidClientId nor google-services.json is available
- **webClientId**: Used for server-side verification and Android fallback
- **hostedDomain**: Restricts sign-in to users from a specific G Suite domain
- **scopes**: Array of OAuth 2.0 scopes to request. Supports:
- GoogleAuthScopes enum for common scopes (recommended for type safety)
- Google API scopes: `https://www.googleapis.com/auth/[service]`
- OpenID Connect scopes: `openid`, `email`, `profile`
- **offlineAccess**: Request refresh token for offline access
#### OAuth Scopes
The library provides a `GoogleAuthScopes` enum for type-safe scope definitions:
```typescript
import { GoogleAuthScopes } from 'react-native-google-auth';
// Use predefined scopes for type safety
await GoogleAuth.configure({
scopes: [
GoogleAuthScopes.EMAIL,
GoogleAuthScopes.PROFILE,
GoogleAuthScopes.DRIVE_READONLY,
GoogleAuthScopes.CALENDAR,
]
});
// Or mix with custom scopes
await GoogleAuth.configure({
scopes: [
GoogleAuthScopes.EMAIL,
'https://www.googleapis.com/auth/custom.scope'
]
});
```
**Available Scopes:**
- **OpenID Connect**: `OPENID`, `EMAIL`, `PROFILE`
- **Google Drive**: `DRIVE`, `DRIVE_FILE`, `DRIVE_READONLY`
- **Gmail**: `GMAIL_READONLY`, `GMAIL_MODIFY`, `GMAIL_COMPOSE`
- **Calendar**: `CALENDAR`, `CALENDAR_READONLY`
- **Contacts**: `CONTACTS`, `CONTACTS_READONLY`
- **YouTube**: `YOUTUBE`, `YOUTUBE_READONLY`
- **Photos**: `PHOTOS`, `PHOTOS_READONLY`
- **Google Workspace**: `SPREADSHEETS`, `DOCUMENTS`, `PRESENTATIONS` (with readonly variants)
- **Cloud Platform**: `CLOUD_PLATFORM`, `CLOUD_PLATFORM_READONLY`
- **Analytics**: `ANALYTICS`, `ANALYTICS_READONLY`
- **Fitness**: `FITNESS_ACTIVITY_READ`, `FITNESS_BODY_READ`, `FITNESS_LOCATION_READ`
- **Other**: `USERINFO_EMAIL`, `USERINFO_PROFILE`, `PLUS_ME`, `ADWORDS`, `BLOGGER`
#### Configuration Validation
The library automatically validates:
- Client ID format (must match Google OAuth format)
- Domain format for hosted domains
- OAuth scope format and validity
- Required parameters based on platform
- Automatic detection fallbacks for both iOS and Android
```
### Sign In
```typescript
const signIn = async () => {
try {
const response = await GoogleAuth.signIn();
if (response.type === 'success') {
console.log('User signed in:', response.data.user);
console.log('Access token:', response.data.accessToken);
console.log('ID token:', response.data.idToken);
// response.data.user contains: id, email, name, photo, etc.
} else if (response.type === 'cancelled') {
console.log('Sign in was cancelled by user');
} else if (response.type === 'noSavedCredentialFound') {
console.log('No saved credential found');
}
} catch (error) {
console.error('Sign in failed:', error);
}
};
```
### Sign Out
```typescript
const signOut = async () => {
try {
await GoogleAuth.signOut();
console.log('User signed out');
} catch (error) {
console.error('Sign out failed:', error);
}
};
```
### Get Tokens
```typescript
const getTokens = async () => {
try {
const tokens = await GoogleAuth.getTokens();
console.log('Tokens:', tokens);
// tokens contains: accessToken, idToken, etc.
} catch (error) {
console.error('Failed to get tokens:', error);
}
};
```
### Refresh Tokens
```typescript
const refreshTokens = async () => {
try {
const refreshedTokens = await GoogleAuth.refreshTokens();
console.log('Refreshed tokens:', refreshedTokens);
// refreshedTokens contains: accessToken, idToken, user, expiresAt
} catch (error) {
console.error('Failed to refresh tokens:', error);
}
};
```
### Check Token Expiration
```typescript
const checkTokenExpiration = async () => {
try {
const isExpired = await GoogleAuth.isTokenExpired();
console.log('Token expired:', isExpired);
if (isExpired) {
// Automatically refresh tokens
await refreshTokens();
}
} catch (error) {
console.error('Failed to check token expiration:', error);
}
};
```
### Get Current User
```typescript
const getCurrentUser = async () => {
try {
const currentUser = await GoogleAuth.getCurrentUser();
if (currentUser) {
console.log('Current user:', currentUser);
// currentUser contains: id, name, email, photo, familyName, givenName
} else {
console.log('No user currently signed in');
}
} catch (error) {
console.error('Failed to get current user:', error);
}
};
```
### Check Play Services
```typescript
const checkPlayServices = async () => {
try {
const playServicesInfo = await GoogleAuth.checkPlayServices();
console.log('Play Services available:', playServicesInfo.isAvailable);
if (playServicesInfo.status) {
console.log('Play Services status:', playServicesInfo.status);
}
} catch (error) {
console.error('Play Services check failed:', error);
}
};
```
*Note: This method is primarily useful on Android to check if Google Play Services are available. On iOS, it always returns `{ isAvailable: true }` since Play Services are not required.*
## Complete Example
```typescript
import React, { useEffect, useState } from 'react';
import { View, Button, Text, Alert } from 'react-native';
import { GoogleAuth } from 'react-native-google-auth';
const GoogleAuthExample = () => {
const [user, setUser] = useState(null);
const [isConfigured, setIsConfigured] = useState(false);
const [tokens, setTokens] = useState(null);
const [tokenExpired, setTokenExpired] = useState(false);
useEffect(() => {
configureGoogleAuth();
checkCurrentUser();
}, []);
const configureGoogleAuth = async () => {
try {
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID',
androidClientId: 'YOUR_ANDROID_CLIENT_ID',
webClientId: 'YOUR_WEB_CLIENT_ID'
});
setIsConfigured(true);
} catch (error) {
Alert.alert('Configuration Error', error.message);
}
};
const checkCurrentUser = async () => {
try {
const currentUser = await GoogleAuth.getCurrentUser();
if (currentUser) {
setUser(currentUser);
await checkTokenExpiration();
}
} catch (error) {
console.log('No current user:', error.message);
}
};
const checkTokenExpiration = async () => {
try {
const isExpired = await GoogleAuth.isTokenExpired();
setTokenExpired(isExpired);
if (isExpired) {
Alert.alert('Token Expired', 'Your session has expired. Please refresh tokens.');
}
} catch (error) {
console.error('Failed to check token expiration:', error);
}
};
const handleSignIn = async () => {
try {
const response = await GoogleAuth.signIn();
if (response.type === 'success') {
setUser(response.data.user);
setTokenExpired(false);
Alert.alert('Success', 'Signed in successfully!');
} else if (response.type === 'cancelled') {
Alert.alert('Cancelled', 'Sign in was cancelled');
} else if (response.type === 'noSavedCredentialFound') {
Alert.alert('No Saved Credential', 'No saved credential found, please sign in manually');
}
} catch (error) {
Alert.alert('Sign In Error', error.message);
}
};
const handleSignOut = async () => {
try {
await GoogleAuth.signOut();
setUser(null);
setTokens(null);
setTokenExpired(false);
} catch (error) {
Alert.alert('Sign Out Error', error.message);
}
};
const handleRefreshTokens = async () => {
try {
const refreshedTokens = await GoogleAuth.refreshTokens();
setTokens(refreshedTokens);
setTokenExpired(false);
Alert.alert('Success', 'Tokens refreshed successfully!');
} catch (error) {
Alert.alert('Refresh Error', error.message);
}
};
const handleGetTokens = async () => {
try {
const currentTokens = await GoogleAuth.getTokens();
setTokens(currentTokens);
Alert.alert('Tokens Retrieved', 'Check console for token details');
console.log('Current tokens:', currentTokens);
} catch (error) {
Alert.alert('Token Error', error.message);
}
};
if (!isConfigured) {
return <Text>Configuring Google Auth...</Text>;
}
return (
<View style={{ padding: 20 }}>
{user ? (
<View>
<Text>Welcome, {user.name}!</Text>
<Text>Email: {user.email}</Text>
{tokenExpired && (
<Text style={{ color: 'red' }}>⚠️ Token Expired</Text>
)}
<View style={{ marginTop: 10 }}>
<Button title="Sign Out" onPress={handleSignOut} />
<View style={{ marginTop: 5 }} />
<Button title="Get Tokens" onPress={handleGetTokens} />
<View style={{ marginTop: 5 }} />
<Button title="Refresh Tokens" onPress={handleRefreshTokens} />
<View style={{ marginTop: 5 }} />
<Button title="Check Token Expiration" onPress={checkTokenExpiration} />
</View>
</View>
) : (
<Button title="Sign In with Google" onPress={handleSignIn} />
)}
</View>
);
};
export default GoogleAuthExample;
```
## Error Handling
```typescript
import { GoogleAuthError, GoogleAuthErrorCodes } from 'react-native-google-auth';
try {
await GoogleAuth.signIn();
} catch (error) {
switch (error.code) {
case GoogleAuthErrorCodes.SIGN_IN_CANCELLED:
console.log('User cancelled sign in');
break;
case GoogleAuthErrorCodes.IN_PROGRESS:
console.log('Sign in already in progress');
break;
case GoogleAuthErrorCodes.PLAY_SERVICES_NOT_AVAILABLE:
console.log('Play Services not available');
break;
case GoogleAuthErrorCodes.TOKEN_EXPIRED:
console.log('Token has expired');
break;
case GoogleAuthErrorCodes.NOT_SIGNED_IN:
console.log('User is not signed in');
break;
default:
console.error('Unknown error:', error.message);
}
}
```
## API Reference
### Methods
| Method | Platform | Description |
|--------|----------|-------------|
| `configure(config)` | iOS, Android | Configure Google Auth with client IDs |
| `signIn()` | iOS, Android | Sign in with Google using One Tap or standard flow |
| `signOut()` | iOS, Android | Sign out current user |
| `getTokens()` | iOS, Android | Get access and ID tokens for current user |
| `refreshTokens()` | iOS, Android | Refresh access and ID tokens |
| `isTokenExpired()` | iOS, Android | Check if current token is expired |
| `getCurrentUser()` | iOS, Android | Get current authenticated user info |
| `checkPlayServices(showErrorDialog?)` | Android | Check if Play Services is available |
### Configuration Options
```typescript
interface ConfigureParams {
iosClientId?: string; // iOS OAuth client ID
androidClientId?: string; // Android OAuth client ID (preferred for Android)
webClientId?: string; // Web OAuth client ID (fallback for Android, required for server verification)
scopes?: string[]; // Additional OAuth scopes to request (use GoogleAuthScopes enum for common scopes)
hostedDomain?: string; // G Suite domain restriction
offlineAccess?: boolean; // Request offline access (refresh tokens)
forceCodeForRefreshToken?: boolean; // Force authorization code for refresh tokens
accountName?: string; // Account name hint
profileImageSize?: number; // Profile image size in pixels
openIdRealm?: string; // OpenID realm
}
// GoogleAuthScopes enum for type-safe scope definitions
enum GoogleAuthScopes {
EMAIL = 'email',
PROFILE = 'profile',
OPENID = 'openid',
DRIVE_READONLY = 'https://www.googleapis.com/auth/drive.readonly',
CALENDAR_READONLY = 'https://www.googleapis.com/auth/calendar.readonly',
GMAIL_READONLY = 'https://www.googleapis.com/auth/gmail.readonly',
PHOTOS_READONLY = 'https://www.googleapis.com/auth/photoslibrary.readonly'
}
```
### User Info Response
```typescript
interface User {
id: string; // User's Google ID
name: string | null; // User's display name
email: string; // User's email
photo: string | null; // User's profile photo URL
familyName: string | null; // User's family name
givenName: string | null; // User's given name
}
```
### Sign In Response
```typescript
type OneTapResponse =
| { type: 'success'; data: { idToken: string; accessToken: string | null; user: User; } }
| { type: 'noSavedCredentialFound' }
| { type: 'cancelled' };
```
**Platform Differences:**
- **iOS**: Returns both `idToken` and `accessToken` when available
- **Android**: Returns `idToken` but `accessToken` is always `null` due to Credential Manager API limitations <mcreference link="https://developers.google.com/identity/android-credential-manager" index="4">4</mcreference>
> **Note**: Android's Credential Manager API focuses on authentication (ID tokens) rather than authorization (access tokens). <mcreference link="https://developers.google.com/identity/protocols/oauth2" index="1">1</mcreference> If you need access tokens on Android for API calls, consider implementing a separate OAuth2 flow or use the ID token for server-side token exchange.
```
### Tokens Response
```typescript
interface GetTokensResponse {
idToken: string; // OpenID Connect ID token
accessToken: string; // OAuth access token (null on Android)
expiresAt?: number; // Unix timestamp when token expires
}
interface RefreshTokensResponse {
idToken: string; // Refreshed OpenID Connect ID token
accessToken: string; // Refreshed OAuth access token (null on Android)
expiresAt?: number; // Unix timestamp when token expires
}
```
**Platform Differences:**
- **iOS**: Returns both `idToken` and `accessToken`
- **Android**: Returns `idToken` but `accessToken` is always `null` due to Credential Manager API limitations <mcreference link="https://developers.google.com/identity/android-credential-manager" index="4">4</mcreference>
```
### Play Services Response
```typescript
interface PlayServicesInfo {
isAvailable: boolean; // Whether Play Services is available
status?: number; // Play Services status code (Android only)
}
```
**Platform Differences:**
- **iOS**: Always returns `{ isAvailable: true }` since iOS doesn't require Google Play Services
- **Android**: Performs actual Google Play Services availability check and returns status code
> **Note**: The `showErrorDialog` parameter only affects Android. On iOS, this parameter is ignored since no actual checking is performed.
## Token Lifecycle Management
### Token Storage and Persistence
**iOS Implementation:**
- Uses GoogleSignIn SDK's built-in token management
- Tokens are automatically stored in iOS Keychain by the SDK
- No manual token persistence required
- Automatic token refresh handled by `GIDSignIn.sharedInstance.currentUser.refreshTokensIfNeeded()`
**Android Implementation:**
- Uses encrypted SharedPreferences for secure token storage
- Manual token caching with thread-safe synchronization
- Implements custom secure storage using `EncryptedSharedPreferences` with AES256 encryption
- Token expiration tracking with Unix timestamps
### Token Refresh Behavior
**iOS:**
- Automatic refresh through GoogleSignIn SDK
- Returns both `idToken` and `accessToken` after refresh
- Built-in expiration checking via `user.accessToken.expirationDate`
**Android:**
- Manual refresh by performing silent sign-in with Credential Manager
- Returns `idToken` only (`accessToken` is always `null`)
- Custom expiration tracking based on ID token payload parsing
### Platform Differences Summary
| Feature | iOS | Android |
|---------|-----|----------|
| Token Storage | iOS Keychain (automatic) | Encrypted SharedPreferences (manual) |
| Access Token | Available | Always `null` |
| Token Refresh | Automatic via SDK | Silent sign-in required |
| Expiration Check | SDK-provided | Custom implementation |
| Persistence | Handled by SDK | Manual secure storage |
### Error Codes
The library provides comprehensive error codes for different scenarios:
```typescript
// Configuration errors
NOT_CONFIGURED // Google Auth not configured
INVALID_CONFIG // Invalid configuration parameters
CONFIG_ERROR // Configuration failed
// Sign-in errors
SIGN_IN_ERROR // General sign-in error
SIGN_IN_CANCELLED // User cancelled sign-in
IN_PROGRESS // Sign-in already in progress
NOT_SIGNED_IN // User is not signed in
// Platform-specific errors
NO_ACTIVITY // No activity available (Android)
NO_VIEW_CONTROLLER // No view controller available (iOS)
// Token errors
TOKEN_ERROR // General token error
TOKEN_REFRESH_ERROR // Token refresh error
TOKEN_REFRESH_FAILED // Token refresh failed
TOKEN_EXPIRED // Token has expired
INVALID_TOKEN // Invalid token
// Play Services errors (Android)
PLAY_SERVICES_NOT_AVAILABLE // Play Services not available
PLAY_SERVICES_ERROR // Play Services error
// Network errors
NETWORK_ERROR // Network connection error
// Implementation errors
NOT_IMPLEMENTED // Feature not implemented
```
## Troubleshooting & FAQ
### Common Issues and Solutions
#### 🔧 Configuration Issues
**Q: "Google Auth not configured" error**
```typescript
// ❌ Wrong - calling signIn before configure
await GoogleAuth.signIn();
// ✅ Correct - configure first
await GoogleAuth.configure({
iosClientId: 'YOUR_IOS_CLIENT_ID',
androidClientId: 'YOUR_ANDROID_CLIENT_ID'
});
await GoogleAuth.signIn();
```
**Q: Invalid configuration parameters**
- Ensure client IDs are correct and match your Google Cloud Console setup
- Verify bundle ID (iOS) and package name (Android) match your app configuration
- Check that OAuth consent screen is properly configured
#### 📱 Platform-Specific Issues
**iOS Issues:**
- **"No view controller available"**: Ensure you're calling Google Auth methods from the main thread
- **"Invalid client ID"**: Verify your iOS client ID in Google Cloud Console
- **App crashes on sign-in**: Check if you've added the URL scheme to `Info.plist`
**Android Issues:**
- **"Play Services not available"**: User needs to update Google Play Services
- **"No activity available"**: Ensure you're calling from a valid React Native context
- **SHA-1 fingerprint issues**: Verify your app's SHA-1 fingerprint is added to Google Cloud Console
#### 🔐 Authentication Flow Issues
**Q: Sign-in cancelled by user**
```typescript
try {
const result = await GoogleAuth.signIn();
if (result.type === 'cancelled') {
console.log('User cancelled sign-in');
// Handle cancellation gracefully
}
} catch (error) {
if (error.code === GoogleAuthErrorCodes.SIGN_IN_CANCELLED) {
// User cancelled the sign-in flow
}
}
```
**Q: Token expired errors**
```typescript
// Check token expiration before making API calls
const isExpired = await GoogleAuth.isTokenExpired();
if (isExpired) {
await GoogleAuth.refreshTokens();
}
```
#### 🌐 Network and Connectivity
**Q: Network errors during sign-in**
- Check internet connectivity
- Verify Google services are not blocked by firewall
- Ensure proper DNS resolution
**Q: "NETWORK_ERROR" when signing in**
```typescript
try {
await GoogleAuth.signIn();
} catch (error) {
if (error.code === GoogleAuthErrorCodes.NETWORK_ERROR) {
// Show user-friendly network error message
Alert.alert('Network Error', 'Please check your internet connection');
}
}
```
### Frequently Asked Questions
#### General Questions
**Q: How do I get Google Client IDs?**
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create or select a project
3. Enable Google Sign-In API
4. Create OAuth 2.0 credentials
5. Configure OAuth consent screen
**Q: What's the difference between iOS and Android Client IDs?**
- **iOS Client ID**: For iOS app authentication
- **Android Client ID**: For Android app authentication
#### Security Questions
**Q: How are tokens stored securely?**
- iOS: Stored in iOS Keychain
- Android: Stored using Android Keystore
- Tokens are encrypted and tied to your app's signature
**Q: How do I verify tokens on my server?**
```typescript
// Get ID token for server verification
const tokens = await GoogleAuth.getTokens();
const idToken = tokens.idToken;
// Send to your server for verification
fetch('/api/verify-google-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken })
});
```
#### Development Questions
**Q: Can I test without Google Play Services?**
- iOS: Yes, works on simulator and device
- Android: Requires Google Play Services or use emulator with Google APIs
**Q: How do I handle different environments (dev/staging/prod)?**
```typescript
const config = {
iosClientId: __DEV__ ? 'DEV_IOS_CLIENT_ID' : 'PROD_IOS_CLIENT_ID',
androidClientId: __DEV__ ? 'DEV_ANDROID_CLIENT_ID' : 'PROD_ANDROID_CLIENT_ID'
};
await GoogleAuth.configure(config);
```
### Performance Optimization
#### Best Practices
1. **Configure once**: Call `configure()` only once in your app lifecycle
2. **Check token expiration**: Verify tokens before API calls
3. **Handle errors gracefully**: Provide user-friendly error messages
4. **Cache user data**: Store user info locally to reduce API calls
#### Memory Management
```typescript
// Good: Check if already configured
if (!GoogleAuth.isConfigured) {
await GoogleAuth.configure(config);
}
// Good: Cleanup on app exit
const handleAppExit = async () => {
await GoogleAuth.signOut();
};
```
### Migration Guide
#### From @react-native-google-signin/google-signin
```typescript
// Old library
import { GoogleSignin } from '@react-native-google-signin/google-signin';
// New library
import { GoogleAuth } from 'react-native-google-auth';
// Configuration changes
// Old:
GoogleSignin.configure({ webClientId: 'CLIENT_ID' });
// New:
GoogleAuth.configure({
iosClientId: 'IOS_CLIENT_ID',
androidClientId: 'ANDROID_CLIENT_ID'
});
// Method changes
// Old:
const userInfo = await GoogleSignin.signIn();
// New:
const response = await GoogleAuth.signIn();
if (response.type === 'success') {
const userInfo = response.data.user;
}
```
## Important Notes
- **Always call `configure()` before using other methods**
- **iOS**: Client ID is automatically detected from `Info.plist` if not provided
- **Android**: Uses the new Credential Manager API (not deprecated GoogleSignIn)
- **Android Client ID Priority**: Android prefers `androidClientId` when provided, falls back to `webClientId`
- **Web Client ID**: Required for server-side verification of tokens and as Android fallback
- **Hosted Domain**: Restricts sign-in to specific G Suite domains
## Contributing
- [Development workflow](CONTRIBUTING.md#development-workflow)
- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
- [Code of conduct](CODE_OF_CONDUCT.md)
## License
MIT
---
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)