Summary
On iOS, rememberSignInWithGoogle runs onIdToken.invoke(...) (which calls auth.signInWith(IDToken)) inside an unguarded scope.launch on the Main dispatcher. When Supabase rejects the token (e.g. BadRequestRestException — "Unacceptable audience in id_token"), the exception escapes the coroutine → kotlinx.coroutines final-resort → processUnhandledException → the app aborts. It never reaches the onResult = NativeSignInResult.Error callback, so apps cannot show an error for a failed Google sign-in on iOS.
Affected code
ComposeAuth/src/appleMain/.../composable/GoogleAuth.kt — the signInCompletion completion callback, else if (idToken != null) branch. Present through 3.6.0 / current main.
} else if (idToken != null) {
logger.d { "Id token available" }
onIdToken.invoke(/* ... */) // throws here (e.g. BadRequest) -> escapes the Main coroutine -> abort
onResult.invoke(NativeSignInResult.Success(SignInResultData.Google()))
}
Why Android and Apple don't crash (the asymmetry is the bug)
- Android
parseCredential wraps signInWithGoogle(idToken) in try/catch → onResult.Error.
- iOS Apple (
AppleAuth.kt, ASAuthorizationController delegate didCompleteWithAuthorization) wraps onIdToken.invoke in try/catch → onResult.Error.
- iOS Google is the only path with no guard around
onIdToken.invoke.
Reproduce
An iOS app using rememberSignInWithGoogle where the native flow returns a valid Google ID token but the Supabase Google provider's configured client ID does not match the serverClientId audience → BadRequest → the app aborts instead of delivering NativeSignInResult.Error. Confirmed live with the "Unacceptable audience in id_token" error.
Proposed fix
Mirror the Apple delegate's handling — wrap the sign-in + success in try/catch:
} else if (idToken != null) {
logger.d { "Id token available" }
- onIdToken.invoke(
- composeAuth = this@rememberSignInWithGoogle,
- result = IdTokenCallback.Result(
- idToken = idToken,
- provider = Google,
- nonce = startedStatus.nonce,
- extraData = startedStatus.extraData
- )
- )
- onResult.invoke(NativeSignInResult.Success(SignInResultData.Google()))
+ try {
+ onIdToken.invoke(
+ composeAuth = this@rememberSignInWithGoogle,
+ result = IdTokenCallback.Result(
+ idToken = idToken,
+ provider = Google,
+ nonce = startedStatus.nonce,
+ extraData = startedStatus.extraData
+ )
+ )
+ onResult.invoke(NativeSignInResult.Success(SignInResultData.Google()))
+ } catch (e: Exception) {
+ coroutineContext.ensureActive()
+ logger.e(e) { "Error logging into Supabase with Google ID Token" }
+ onResult.invoke(NativeSignInResult.Error(e.message ?: "error"))
+ }
}
Happy to open a PR if this looks right.
Environment
- supabase-kt
3.3.0 (also verified the bug is present on current main = 3.6.0)
- Compose Multiplatform on iOS (
iosSimulatorArm64 / iosArm64), Kotlin/Native
Summary
On iOS,
rememberSignInWithGooglerunsonIdToken.invoke(...)(which callsauth.signInWith(IDToken)) inside an unguardedscope.launchon the Main dispatcher. When Supabase rejects the token (e.g.BadRequestRestException— "Unacceptable audience in id_token"), the exception escapes the coroutine →kotlinx.coroutinesfinal-resort →processUnhandledException→ the app aborts. It never reaches theonResult = NativeSignInResult.Errorcallback, so apps cannot show an error for a failed Google sign-in on iOS.Affected code
ComposeAuth/src/appleMain/.../composable/GoogleAuth.kt— thesignInCompletioncompletion callback,else if (idToken != null)branch. Present through 3.6.0 / currentmain.Why Android and Apple don't crash (the asymmetry is the bug)
parseCredentialwrapssignInWithGoogle(idToken)intry/catch → onResult.Error.AppleAuth.kt,ASAuthorizationControllerdelegatedidCompleteWithAuthorization) wrapsonIdToken.invokeintry/catch → onResult.Error.onIdToken.invoke.Reproduce
An iOS app using
rememberSignInWithGooglewhere the native flow returns a valid Google ID token but the Supabase Google provider's configured client ID does not match theserverClientIdaudience →BadRequest→ the app aborts instead of deliveringNativeSignInResult.Error. Confirmed live with the "Unacceptable audience in id_token" error.Proposed fix
Mirror the Apple delegate's handling — wrap the sign-in + success in
try/catch:} else if (idToken != null) { logger.d { "Id token available" } - onIdToken.invoke( - composeAuth = this@rememberSignInWithGoogle, - result = IdTokenCallback.Result( - idToken = idToken, - provider = Google, - nonce = startedStatus.nonce, - extraData = startedStatus.extraData - ) - ) - onResult.invoke(NativeSignInResult.Success(SignInResultData.Google())) + try { + onIdToken.invoke( + composeAuth = this@rememberSignInWithGoogle, + result = IdTokenCallback.Result( + idToken = idToken, + provider = Google, + nonce = startedStatus.nonce, + extraData = startedStatus.extraData + ) + ) + onResult.invoke(NativeSignInResult.Success(SignInResultData.Google())) + } catch (e: Exception) { + coroutineContext.ensureActive() + logger.e(e) { "Error logging into Supabase with Google ID Token" } + onResult.invoke(NativeSignInResult.Error(e.message ?: "error")) + } }Happy to open a PR if this looks right.
Environment
3.3.0(also verified the bug is present on currentmain= 3.6.0)iosSimulatorArm64/iosArm64), Kotlin/Native