Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 47 additions & 12 deletions android/src/main/java/com/googleauth/GoogleAuthModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class GoogleAuthModule(reactContext: ReactApplicationContext) :
private var androidClientId: String? = null
private var hostedDomain: String? = null
private var configuredScopes: List<String>? = null
private var credentialManagerMode: String = "auto" // 'silent', 'interactive', or 'auto'
private var isConfigured = false
private val coroutineScope = CoroutineScope(Dispatchers.Main)

Expand Down Expand Up @@ -125,7 +126,16 @@ class GoogleAuthModule(reactContext: ReactApplicationContext) :
webClientId = params.getString("webClientId")
androidClientId = params.getString("androidClientId")
hostedDomain = params.getString("hostedDomain")


// Extract credential manager mode (default to "auto" if not specified)
credentialManagerMode = params.getString("credentialManagerMode") ?: "auto"

// Validate credential manager mode
if (credentialManagerMode !in listOf("silent", "interactive", "auto")) {
promise.reject("INVALID_CONFIG", "credentialManagerMode must be 'silent', 'interactive', or 'auto'")
return
}

// Extract and validate scopes
val scopesArray = params.getArray("scopes")
configuredScopes = scopesArray?.let { array ->
Expand Down Expand Up @@ -192,18 +202,43 @@ class GoogleAuthModule(reactContext: ReactApplicationContext) :
return@launch
}

// Try silent sign-in first
try {
val silentResult = performSilentSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(silentResult)
when (credentialManagerMode) {
"silent" -> {
// Silent mode only - no fallback to interactive
try {
val silentResult = performSilentSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(silentResult)
}
} catch (e: Exception) {
Log.e("GoogleAuth", "Silent sign-in failed: " + (e.localizedMessage ?: "Unknown error"))
withContext(Dispatchers.Main) {
promise.reject("SIGN_IN_ERROR", "Silent sign-in failed. No saved credentials found or user not previously authorized: " + (e.localizedMessage ?: "Unknown error"), e)
}
}
}
"interactive" -> {
// Interactive mode only - always show account picker
val interactiveResult = performInteractiveSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(interactiveResult)
}
}
} catch (e: Exception) {
Log.d("GoogleAuth", "Silent sign-in failed, trying interactive: " + (e.localizedMessage ?: "Unknown error"))
// If silent fails, try interactive
val interactiveResult = performInteractiveSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(interactiveResult)
else -> {
// Auto mode (default) - try silent first, fallback to interactive
try {
val silentResult = performSilentSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(silentResult)
}
} catch (e: Exception) {
Log.d("GoogleAuth", "Silent sign-in failed, trying interactive: " + (e.localizedMessage ?: "Unknown error"))
// If silent fails, try interactive
val interactiveResult = performInteractiveSignIn(activity)
withContext(Dispatchers.Main) {
promise.resolve(interactiveResult)
}
}
}
}
} catch (e: Exception) {
Expand Down
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ PODS:
- FBLazyVector (0.81.0)
- fmt (11.0.2)
- glog (0.3.5)
- GoogleAuth (2.1.0):
- GoogleAuth (1.2.1):
- boost
- DoubleConversion
- fast_float
Expand Down Expand Up @@ -2598,7 +2598,7 @@ SPEC CHECKSUMS:
FBLazyVector: a867936a67af0d09c37935a1b900a1a3c795b6d1
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
GoogleAuth: d45f30ae4d49edbaf5e48d56586e164b925bf004
GoogleAuth: eec941506f196ee17b5e9a74a3b83e720d599232
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
Expand Down Expand Up @@ -2665,7 +2665,7 @@ SPEC CHECKSUMS:
React-timing: 25e8229ad1cf6874e9f0711515213cb2bc322215
React-utils: 068cec677032ba78ca0700f2dcbe6d08a0939647
ReactAppDependencyProvider: c91900fa724baee992f01c05eeb4c9e01a807f78
ReactCodegen: 5695f203204e30acbf7d6c06dbb8d0f391e52133
ReactCodegen: a55799cae416c387aeaae3aabc1bc0289ac19cee
ReactCommon: 116d6ee71679243698620d8cd9a9042541e44aa6
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 00013dd9cde63a2d98e8002fcc4f5ddb66c10782
Expand Down
10 changes: 10 additions & 0 deletions src/NativeGoogleAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ export interface ConfigureParams {
* @platform iOS
*/
forceAccountPicker?: boolean;

/**
* Android Credential Manager behavior mode
* - 'silent': Only show existing authorized accounts, no UI interaction
* - 'interactive': Always display the Google account picker UI
* - 'auto': Try silent sign-in first, fallback to interactive if needed (default)
* Default: 'auto'
* @platform Android
*/
credentialManagerMode?: 'silent' | 'interactive' | 'auto';
}

export interface User {
Expand Down
Loading