From f6c3c391b0cebc7c0af8840d5ef00e9893480af1 Mon Sep 17 00:00:00 2001 From: Ahmed Sbai Date: Wed, 10 Dec 2025 01:14:48 +0100 Subject: [PATCH 1/2] feat(google-auth): add forceAccountPicker option for explicit account selection - Introduced a new `forceAccountPicker` parameter to skip silent sign-in. - Updated iOS implementation to handle this behavior. - Documented the new option in the TypeScript interface. --- ios/GoogleAuth.swift | 28 +++++++++++++++++++++------- src/NativeGoogleAuth.ts | 9 +++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ios/GoogleAuth.swift b/ios/GoogleAuth.swift index 1f387b3..97a07ac 100644 --- a/ios/GoogleAuth.swift +++ b/ios/GoogleAuth.swift @@ -4,12 +4,13 @@ import GoogleSignIn @objc(GoogleAuth) class GoogleAuth: NSObject { - + @objc static let shared = GoogleAuth() private var isConfigured = false - + private var configuredScopes: [String] = [] - + private var forceAccountPicker: Bool = false + private override init() { super.init() } @@ -44,7 +45,13 @@ class GoogleAuth: NSObject { if let scopes = params["scopes"] as? [String] { validateAndStoreScopes(scopes) } - + + // Store forceAccountPicker preference + if let forceAccountPicker = params["forceAccountPicker"] as? Bool { + self.forceAccountPicker = forceAccountPicker + print("GoogleAuth: forceAccountPicker set to \(forceAccountPicker)") + } + isConfigured = true print("GoogleAuth: Configuration completed successfully") } catch { @@ -61,13 +68,20 @@ class GoogleAuth: NSObject { reject("NOT_CONFIGURED", "GoogleAuth must be configured before signing in", nil) return } - + DispatchQueue.main.async { guard let presentingViewController = self.getPresentingViewController() else { reject("NO_VIEW_CONTROLLER", "No presenting view controller found", nil) return } - + + // If forceAccountPicker is enabled, skip silent sign-in and show account picker directly + if self.forceAccountPicker { + print("GoogleAuth: forceAccountPicker enabled, skipping silent sign-in") + self.performInteractiveSignIn(presentingViewController: presentingViewController, resolve: resolve, reject: reject) + return + } + // Try silent sign-in first GIDSignIn.sharedInstance.restorePreviousSignIn { [weak self] result, error in if let error = error { @@ -75,7 +89,7 @@ class GoogleAuth: NSObject { self?.performInteractiveSignIn(presentingViewController: presentingViewController, resolve: resolve, reject: reject) return } - + if let user = result { self?.handleSignInSuccess(user: user, resolve: resolve) } else { diff --git a/src/NativeGoogleAuth.ts b/src/NativeGoogleAuth.ts index 91fa59f..898058d 100644 --- a/src/NativeGoogleAuth.ts +++ b/src/NativeGoogleAuth.ts @@ -109,6 +109,15 @@ export interface ConfigureParams { * Legacy parameter for specific use cases */ openIdRealm?: string; + + /** + * Force the account picker to show even if a user is already signed in + * When true, skips silent sign-in and always shows the account selection UI + * Useful when you want users to explicitly choose between multiple Google accounts + * Default: false + * @platform iOS + */ + forceAccountPicker?: boolean; } export interface User { From 66ed50b93a48fcf158d259ee6ba34e3ffc39eadb Mon Sep 17 00:00:00 2001 From: Ahmed Sbai Date: Wed, 10 Dec 2025 08:54:19 +0100 Subject: [PATCH 2/2] docs(google-auth): clarify androidClientId usage and update configuration guide - Emphasized the requirement to use a Web OAuth client ID for `androidClientId`. - Added detailed instructions and notes for Google Cloud Console setup. - Updated troubleshooting section to address common configuration errors. --- README.md | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2ca3c28..a30bd38 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,8 @@ 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', + iosClientId: 'YOUR_IOS_CLIENT_ID.apps.googleusercontent.com', + androidClientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com', // Use Web OAuth client ID for Android scopes: [GoogleAuthScopes.EMAIL, GoogleAuthScopes.PROFILE] }); @@ -97,6 +97,8 @@ if (response.type === 'success') { } ``` +> **Android Note:** The `androidClientId` must be a **Web application OAuth client ID** (not Android OAuth client), as required by the Android Credential Manager API. + ## 📱 Platform Setup ### Expo Setup (Recommended) @@ -344,19 +346,23 @@ interface GoogleAuthPluginOptions { 1. **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. + > **Important:** The library will automatically extract the Web client ID (client_type: 3) from your `google-services.json`. This is the correct client ID for Android Credential Manager authentication. + **Method B: Manual Configuration** - - Provide the client ID directly in your configuration: + + Provide the **Web application** client ID directly in your configuration: ```typescript await GoogleAuth.configure({ - androidClientId: 'YOUR_ANDROID_CLIENT_ID.apps.googleusercontent.com', + androidClientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com', // Use Web OAuth client ID, NOT Android client ID iosClientId: 'YOUR_IOS_CLIENT_ID.apps.googleusercontent.com' }); ``` + > **Note:** The `androidClientId` should be your **Web application OAuth client ID** (client_type: 3 in google-services.json), not the Android OAuth client ID. The Android OAuth client is used only for linking your SHA-1 certificate to the project. + ## 🔧 Google Cloud Console Setup ### Step 1: Create a Google Cloud Project @@ -387,29 +393,45 @@ interface GoogleAuthPluginOptions { 6. Copy the **Client ID** (ends with `.apps.googleusercontent.com`) #### For Android: + +**Important:** For Android, you need to create **both** an Android OAuth client AND a Web application OAuth client. + +**Step 1: Create Android OAuth Client (for SHA-1 certificate)** 1. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client IDs** 2. Application type: **Android** 3. Name: Your app name (Android) 4. Package name: Your Android app's package name (e.g., `com.yourcompany.yourapp`) 5. SHA-1 certificate fingerprint: - + **For development:** ```bash keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android ``` - + **For Expo development builds:** ```bash eas credentials -p android ``` - + **For production:** ```bash keytool -list -v -keystore path/to/your/release.keystore -alias your-key-alias ``` 6. Click **Create** -7. Copy the **Client ID** (ends with `.apps.googleusercontent.com`) + +**Step 2: Create Web Application OAuth Client (Required for Android Authentication)** +1. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client IDs** +2. Application type: **Web application** +3. Name: Your app name (Web) +4. Click **Create** +5. **Copy this Client ID** - this is what you'll use for `androidClientId` in your configuration + +> **Why do I need a Web client ID for Android?** +> +> The Android Credential Manager API requires a Web OAuth client ID (client_type: 3) for authentication. This is used to generate ID tokens and authenticate with your backend server. The Android OAuth client (created in Step 1) is only used for associating your app's package name and SHA-1 certificate with your project. +> +> When you download `google-services.json`, look for the `oauth_client` entry with `"client_type": 3` - this is the Web client ID you should use in your `androidClientId` configuration. ### Step 4: Download Configuration Files (Optional but Recommended) @@ -673,8 +695,10 @@ enum GoogleAuthScopes { **1. "DEVELOPER_ERROR" on Android** - Verify your package name matches Google Cloud Console -- Check SHA-1 fingerprint is correctly added -- Ensure `google-services.json` is in the correct location +- Check SHA-1 fingerprint is correctly added to the Android OAuth client +- Ensure you're using the **Web application OAuth client ID** (client_type: 3), not the Android OAuth client ID +- Verify `google-services.json` is in the correct location (`android/app/`) +- If manually configuring, ensure `androidClientId` is set to your Web OAuth client ID **2. "SIGN_IN_REQUIRED" error** - User needs to sign in first