From d4c7541c18c4682c6cca7393309428fcd632f487 Mon Sep 17 00:00:00 2001 From: demolaf Date: Tue, 19 May 2026 11:50:17 +0100 Subject: [PATCH 1/4] fix(auth): update AuthState to reflect success or idle based on user result --- .../android/demo/HighLevelApiDemoActivity.kt | 2 +- .../firebaseui/android/demo/MainActivity.kt | 2 +- .../com/firebase/ui/auth/FirebaseAuthUI.kt | 13 ++ .../AnonymousAuthProvider+FirebaseAuthUI.kt | 4 +- .../EmailAuthProvider+FirebaseAuthUI.kt | 8 +- .../OAuthProvider+FirebaseAuthUI.kt | 4 +- .../ui/auth/ui/screens/FirebaseAuthScreen.kt | 2 +- ...AnonymousAuthProviderFirebaseAuthUITest.kt | 4 +- .../EmailAuthProviderFirebaseAuthUITest.kt | 147 ++++++++++++++++++ .../GoogleAuthProviderFirebaseAuthUITest.kt | 12 +- .../OAuthProviderFirebaseAuthUITest.kt | 6 +- 11 files changed, 181 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt b/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt index ff008abcf..a4c708a6b 100644 --- a/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt +++ b/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt @@ -247,7 +247,7 @@ private fun AppAuthenticatedContent( } }, state = rememberTooltipState( - initialIsVisible = !configuration.isMfaEnabled + initialIsVisible = false ) ) { Button( diff --git a/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt b/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt index 300014174..67e95e184 100644 --- a/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt +++ b/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt @@ -36,7 +36,7 @@ import com.google.firebase.FirebaseApp */ class MainActivity : ComponentActivity() { companion object { - private const val USE_AUTH_EMULATOR = false + private const val USE_AUTH_EMULATOR = true private const val AUTH_EMULATOR_HOST = "10.0.2.2" private const val AUTH_EMULATOR_PORT = 9099 } diff --git a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt index af1daa3c0..20e953581 100644 --- a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt @@ -23,6 +23,7 @@ import com.firebase.ui.auth.configuration.auth_provider.signOutFromFacebook import com.firebase.ui.auth.configuration.auth_provider.signOutFromGoogle import com.google.firebase.Firebase import com.google.firebase.FirebaseApp +import com.google.firebase.auth.AuthResult import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseAuth.AuthStateListener import com.google.firebase.auth.FirebaseAuth.IdTokenListener @@ -325,6 +326,18 @@ class FirebaseAuthUI private constructor( _authStateFlow.value = state } + internal fun updateAuthStateWithResult(result: AuthResult?, defaultIsNewUser: Boolean = false) { + if (result?.user != null) { + updateAuthState(AuthState.Success( + result = result, + user = result.user!!, + isNewUser = result.additionalUserInfo?.isNewUser ?: defaultIsNewUser + )) + } else { + updateAuthState(AuthState.Idle) + } + } + /** * Signs out the current user and clears authentication state. * diff --git a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProvider+FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProvider+FirebaseAuthUI.kt index 746537390..baf9cef82 100644 --- a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProvider+FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProvider+FirebaseAuthUI.kt @@ -110,8 +110,8 @@ internal fun FirebaseAuthUI.rememberAnonymousSignInHandler(): () -> Unit { internal suspend fun FirebaseAuthUI.signInAnonymously() { try { updateAuthState(AuthState.Loading("Signing in anonymously...")) - auth.signInAnonymously().await() - updateAuthState(AuthState.Idle) + val result = auth.signInAnonymously().await() + updateAuthStateWithResult(result, defaultIsNewUser = true) } catch (e: CancellationException) { val cancelledException = AuthException.AuthCancelledException( message = "Sign in anonymously was cancelled", diff --git a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProvider+FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProvider+FirebaseAuthUI.kt index 61b50c613..670b451bc 100644 --- a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProvider+FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProvider+FirebaseAuthUI.kt @@ -197,7 +197,7 @@ internal suspend fun FirebaseAuthUI.createOrLinkUserWithEmailAndPassword( } } - updateAuthState(AuthState.Idle) + updateAuthStateWithResult(result, defaultIsNewUser = true) return result } catch (e: FirebaseAuthUserCollisionException) { // Account collision: email already exists @@ -431,7 +431,7 @@ internal suspend fun FirebaseAuthUI.signInWithEmailAndPassword( } } - updateAuthState(AuthState.Idle) + updateAuthStateWithResult(result) } } catch (e: FirebaseAuthMultiFactorException) { // MFA required - extract resolver and update state @@ -557,7 +557,7 @@ internal suspend fun FirebaseAuthUI.signInAndLinkWithCredential( result?.user?.let { mergeProfile(auth, displayName, photoUrl) } - updateAuthState(AuthState.Idle) + updateAuthStateWithResult(result) } } catch (e: FirebaseAuthMultiFactorException) { // MFA required - extract resolver and update state @@ -974,7 +974,7 @@ internal suspend fun FirebaseAuthUI.signInWithEmailLink( } // Clear DataStore after success persistenceManager.clear(context) - updateAuthState(AuthState.Idle) + updateAuthStateWithResult(result) return result } catch (e: CancellationException) { val cancelledException = AuthException.AuthCancelledException( diff --git a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProvider+FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProvider+FirebaseAuthUI.kt index 4053684d6..e2d141400 100644 --- a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProvider+FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProvider+FirebaseAuthUI.kt @@ -162,7 +162,6 @@ internal suspend fun FirebaseAuthUI.signInWithProvider( photoUrl = authResult.user?.photoUrl, ) } - updateAuthState(AuthState.Idle) return } @@ -195,8 +194,7 @@ internal suspend fun FirebaseAuthUI.signInWithProvider( android.util.Log.w("OAuthProvider", "Failed to save sign-in preference", e) } - // Just update state to Idle - updateAuthState(AuthState.Idle) + updateAuthStateWithResult(authResult) } else { throw AuthException.UnknownException( message = "OAuth sign-in did not return a valid credential" diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/screens/FirebaseAuthScreen.kt b/auth/src/main/java/com/firebase/ui/auth/ui/screens/FirebaseAuthScreen.kt index 7a67b977e..9a7e3911a 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/screens/FirebaseAuthScreen.kt +++ b/auth/src/main/java/com/firebase/ui/auth/ui/screens/FirebaseAuthScreen.kt @@ -780,7 +780,7 @@ private fun AuthSuccessContent( } }, state = rememberTooltipState( - initialIsVisible = !configuration.isMfaEnabled + initialIsVisible = false ) ) { Button( diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProviderFirebaseAuthUITest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProviderFirebaseAuthUITest.kt index 53f465b9a..7ddfb3ac8 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProviderFirebaseAuthUITest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AnonymousAuthProviderFirebaseAuthUITest.kt @@ -110,8 +110,8 @@ class AnonymousAuthProviderFirebaseAuthUITest { verify(mockFirebaseAuth).signInAnonymously() - val finalState = instance.authStateFlow().first { it is AuthState.Idle } - assertThat(finalState).isInstanceOf(AuthState.Idle::class.java) + val finalState = instance.authStateFlow().first { it is AuthState.Success } + assertThat(finalState).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = true)) } @Test diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProviderFirebaseAuthUITest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProviderFirebaseAuthUITest.kt index dc027e3dc..d42bbab5f 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProviderFirebaseAuthUITest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/EmailAuthProviderFirebaseAuthUITest.kt @@ -1457,4 +1457,151 @@ class EmailAuthProviderFirebaseAuthUITest { assertThat(e).isNotNull() } } + + @Test + fun `signInWithEmailAndPassword - emits AuthState Success with non-null result`() = runTest { + val mockUser = mock(FirebaseUser::class.java) + val mockAuthResult = mock(AuthResult::class.java) + `when`(mockAuthResult.user).thenReturn(mockUser) + val taskCompletionSource = TaskCompletionSource() + taskCompletionSource.setResult(mockAuthResult) + `when`(mockFirebaseAuth.signInWithEmailAndPassword("test@example.com", "Pass@123")) + .thenReturn(taskCompletionSource.task) + + val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) + val emailProvider = AuthProvider.Email( + emailLinkActionCodeSettings = null, + passwordValidationRules = emptyList() + ) + val config = authUIConfiguration { + context = applicationContext + providers { provider(emailProvider) } + } + + instance.signInWithEmailAndPassword( + context = applicationContext, + config = config, + email = "test@example.com", + password = "Pass@123" + ) + + val state = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(state).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) + } + + @Test + fun `signInAndLinkWithCredential - emits AuthState Success with non-null result`() = runTest { + val credential = GoogleAuthProvider.getCredential("google-id-token", null) + val mockUser = mock(FirebaseUser::class.java) + val mockAuthResult = mock(AuthResult::class.java) + `when`(mockAuthResult.user).thenReturn(mockUser) + val taskCompletionSource = TaskCompletionSource() + taskCompletionSource.setResult(mockAuthResult) + `when`(mockFirebaseAuth.signInWithCredential(credential)) + .thenReturn(taskCompletionSource.task) + + val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) + val emailProvider = AuthProvider.Email( + emailLinkActionCodeSettings = null, + passwordValidationRules = emptyList() + ) + val config = authUIConfiguration { + context = applicationContext + providers { provider(emailProvider) } + } + + instance.signInAndLinkWithCredential(config = config, credential = credential) + + val state = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(state).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) + } + + @Test + fun `createOrLinkUserWithEmailAndPassword - emits AuthState Success with non-null result`() = runTest { + val mockUser = mock(FirebaseUser::class.java) + val mockAuthResult = mock(AuthResult::class.java) + `when`(mockAuthResult.user).thenReturn(mockUser) + val taskCompletionSource = TaskCompletionSource() + taskCompletionSource.setResult(mockAuthResult) + `when`(mockFirebaseAuth.createUserWithEmailAndPassword("new@example.com", "Pass@123")) + .thenReturn(taskCompletionSource.task) + + val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) + val emailProvider = AuthProvider.Email( + emailLinkActionCodeSettings = null, + passwordValidationRules = emptyList() + ) + val config = authUIConfiguration { + context = applicationContext + providers { provider(emailProvider) } + } + + instance.createOrLinkUserWithEmailAndPassword( + context = applicationContext, + config = config, + provider = emailProvider, + name = null, + email = "new@example.com", + password = "Pass@123" + ) + + val state = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(state).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = true)) + } + + @Test + fun `signInWithEmailLink - emits AuthState Success with non-null result`() = runTest { + val mockUser = mock(FirebaseUser::class.java) + `when`(mockUser.email).thenReturn("test@example.com") + `when`(mockUser.isAnonymous).thenReturn(false) + val mockAuthResult = mock(AuthResult::class.java) + `when`(mockAuthResult.user).thenReturn(mockUser) + + `when`(mockFirebaseAuth.currentUser).thenReturn(null) + `when`(mockFirebaseAuth.isSignInWithEmailLink(anyString())).thenReturn(true) + + val taskCompletionSource = TaskCompletionSource() + taskCompletionSource.setResult(mockAuthResult) + `when`(mockFirebaseAuth.signInWithCredential(any())).thenReturn(taskCompletionSource.task) + + val provider = AuthProvider.Email( + isEmailLinkSignInEnabled = true, + emailLinkActionCodeSettings = ActionCodeSettings.newBuilder() + .setUrl("https://example.com") + .setHandleCodeInApp(true) + .build(), + passwordValidationRules = emptyList() + ) + val config = authUIConfiguration { + context = applicationContext + providers { provider(provider) } + } + + val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) + + val mockPersistence = MockPersistenceManager() + mockPersistence.setSessionRecord( + EmailLinkPersistenceManager.SessionRecord( + sessionId = "session123", + email = "test@example.com", + anonymousUserId = null, + credentialForLinking = null + ) + ) + + val emailLink = + "https://example.com/__/auth/action?apiKey=key&mode=signIn&oobCode=code&continueUrl=https://example.com?ui_sid=session123" + + instance.signInWithEmailLink( + context = applicationContext, + config = config, + provider = provider, + email = "test@example.com", + emailLink = emailLink, + persistenceManager = mockPersistence + ) + + val state = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(state).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) + } } diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/GoogleAuthProviderFirebaseAuthUITest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/GoogleAuthProviderFirebaseAuthUITest.kt index 2fd855c37..185483b9c 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/GoogleAuthProviderFirebaseAuthUITest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/GoogleAuthProviderFirebaseAuthUITest.kt @@ -180,9 +180,9 @@ class GoogleAuthProviderFirebaseAuthUITest { // Verify Firebase sign-in was called verify(mockFirebaseAuth).signInWithCredential(mockCredential) - // Verify state is Idle after success - val finalState = instance.authStateFlow().first() - assertThat(finalState).isEqualTo(AuthState.Idle) + // Verify state is Success (with the real AuthResult) after sign-in + val finalState = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(finalState).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) } @Test @@ -853,8 +853,8 @@ class GoogleAuthProviderFirebaseAuthUITest { credentialManagerProvider = mockCredentialManagerProvider ) - // Verify final state - val finalState = instance.authStateFlow().first() - assertThat(finalState).isEqualTo(AuthState.Idle) + // Verify final state is Success (with the real AuthResult) + val finalState = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(finalState).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) } } diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProviderFirebaseAuthUITest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProviderFirebaseAuthUITest.kt index 1d027d9ea..672e0c11d 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProviderFirebaseAuthUITest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/OAuthProviderFirebaseAuthUITest.kt @@ -143,9 +143,9 @@ class OAuthProviderFirebaseAuthUITest { any() ) - // Verify state is Idle after success - val finalState = instance.authStateFlow().first() - assertThat(finalState).isEqualTo(AuthState.Idle) + // Verify state is Success after sign-in + val finalState = instance.authStateFlow().first { it !is AuthState.Loading } + assertThat(finalState).isEqualTo(AuthState.Success(result = mockAuthResult, user = mockUser, isNewUser = false)) } // ============================================================================================= From 0b92f3d936138a2724ec70c0f05070c2753629e5 Mon Sep 17 00:00:00 2001 From: demolaf Date: Tue, 19 May 2026 12:11:54 +0100 Subject: [PATCH 2/4] updates --- .../com/firebase/ui/auth/FirebaseAuthUI.kt | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt index 20e953581..6d2c9c872 100644 --- a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt @@ -259,21 +259,7 @@ class FirebaseAuthUI private constructor( val firebaseAuthFlow = callbackFlow { fun buildState(currentUser: FirebaseUser?): AuthState { return if (currentUser != null) { - if (!currentUser.isEmailVerified && - currentUser.email != null && - currentUser.providerData.any { it.providerId == "password" } - ) { - AuthState.RequiresEmailVerification( - user = currentUser, - email = currentUser.email!! - ) - } else { - AuthState.Success( - result = null, - user = currentUser, - isNewUser = false - ) - } + stateForUser(currentUser, result = null, isNewUser = false) } else { AuthState.Idle } @@ -286,6 +272,17 @@ class FirebaseAuthUI private constructor( // Create auth state listener val authStateListener = AuthStateListener { firebaseAuth -> + // When user signs out, clear stale user-presence internal states so the combine + // doesn't return Success/RequiresEmailVerification after the user is gone. + if (firebaseAuth.currentUser == null) { + val current = _authStateFlow.value + if (current is AuthState.Success || + current is AuthState.RequiresEmailVerification || + current is AuthState.RequiresProfileCompletion + ) { + _authStateFlow.value = AuthState.Idle + } + } trySend(buildState(firebaseAuth.currentUser)) } @@ -326,13 +323,27 @@ class FirebaseAuthUI private constructor( _authStateFlow.value = state } + private fun stateForUser(user: FirebaseUser, result: AuthResult?, isNewUser: Boolean): AuthState { + return if (!user.isEmailVerified && + user.email != null && + user.providerData.any { it.providerId == "password" } + ) { + AuthState.RequiresEmailVerification(user = user, email = user.email!!) + } else { + AuthState.Success(result = result, user = user, isNewUser = isNewUser) + } + } + internal fun updateAuthStateWithResult(result: AuthResult?, defaultIsNewUser: Boolean = false) { - if (result?.user != null) { - updateAuthState(AuthState.Success( - result = result, - user = result.user!!, - isNewUser = result.additionalUserInfo?.isNewUser ?: defaultIsNewUser - )) + val user = result?.user + if (user != null) { + updateAuthState( + stateForUser( + user = user, + result = result, + isNewUser = result.additionalUserInfo?.isNewUser ?: defaultIsNewUser + ) + ) } else { updateAuthState(AuthState.Idle) } From f1f092f2f6d552e52b4b7c63754900fa366c0c57 Mon Sep 17 00:00:00 2001 From: demolaf Date: Tue, 19 May 2026 12:12:37 +0100 Subject: [PATCH 3/4] updates --- app/src/main/java/com/firebaseui/android/demo/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt b/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt index 67e95e184..300014174 100644 --- a/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt +++ b/app/src/main/java/com/firebaseui/android/demo/MainActivity.kt @@ -36,7 +36,7 @@ import com.google.firebase.FirebaseApp */ class MainActivity : ComponentActivity() { companion object { - private const val USE_AUTH_EMULATOR = true + private const val USE_AUTH_EMULATOR = false private const val AUTH_EMULATOR_HOST = "10.0.2.2" private const val AUTH_EMULATOR_PORT = 9099 } From df88ef1126ca151ef0614eace756186200e252d0 Mon Sep 17 00:00:00 2001 From: demolaf Date: Wed, 20 May 2026 14:23:54 +0100 Subject: [PATCH 4/4] refactor: rename auth user state handler --- .../com/firebase/ui/auth/FirebaseAuthUI.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt index 6d2c9c872..827c37abd 100644 --- a/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt +++ b/auth/src/main/java/com/firebase/ui/auth/FirebaseAuthUI.kt @@ -259,7 +259,7 @@ class FirebaseAuthUI private constructor( val firebaseAuthFlow = callbackFlow { fun buildState(currentUser: FirebaseUser?): AuthState { return if (currentUser != null) { - stateForUser(currentUser, result = null, isNewUser = false) + handleAuthUserState(currentUser, result = null, isNewUser = false) } else { AuthState.Idle } @@ -323,22 +323,11 @@ class FirebaseAuthUI private constructor( _authStateFlow.value = state } - private fun stateForUser(user: FirebaseUser, result: AuthResult?, isNewUser: Boolean): AuthState { - return if (!user.isEmailVerified && - user.email != null && - user.providerData.any { it.providerId == "password" } - ) { - AuthState.RequiresEmailVerification(user = user, email = user.email!!) - } else { - AuthState.Success(result = result, user = user, isNewUser = isNewUser) - } - } - internal fun updateAuthStateWithResult(result: AuthResult?, defaultIsNewUser: Boolean = false) { val user = result?.user if (user != null) { updateAuthState( - stateForUser( + handleAuthUserState( user = user, result = result, isNewUser = result.additionalUserInfo?.isNewUser ?: defaultIsNewUser @@ -349,6 +338,17 @@ class FirebaseAuthUI private constructor( } } + private fun handleAuthUserState(user: FirebaseUser, result: AuthResult?, isNewUser: Boolean): AuthState { + return if (!user.isEmailVerified && + user.email != null && + user.providerData.any { it.providerId == "password" } + ) { + AuthState.RequiresEmailVerification(user = user, email = user.email!!) + } else { + AuthState.Success(result = result, user = user, isNewUser = isNewUser) + } + } + /** * Signs out the current user and clears authentication state. *