From f95112c919b031a99e096dc12643db142b4bcbb6 Mon Sep 17 00:00:00 2001 From: demolaf Date: Wed, 8 Apr 2026 16:22:38 +0100 Subject: [PATCH 1/2] fix(auth): improve user identifier retrieval --- .../android/demo/HighLevelApiDemoActivity.kt | 5 +-- .../ui/auth/ui/screens/FirebaseAuthScreen.kt | 5 +-- .../com/firebase/ui/auth/util/UserUtils.kt | 32 +++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt 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 fcae3ea9c..e34af6b50 100644 --- a/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt +++ b/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt @@ -42,6 +42,7 @@ import com.firebase.ui.auth.configuration.theme.AuthUITheme import com.firebase.ui.auth.ui.screens.AuthSuccessUiContext import com.firebase.ui.auth.ui.screens.FirebaseAuthScreen import com.firebase.ui.auth.util.EmailLinkConstants +import com.firebase.ui.auth.util.displayIdentifier import com.google.firebase.auth.actionCodeSettings class HighLevelApiDemoActivity : ComponentActivity() { @@ -211,7 +212,7 @@ private fun AppAuthenticatedContent( when (state) { is AuthState.Success -> { val user = uiContext.authUI.getCurrentUser() - val identifier = user?.email ?: user?.phoneNumber ?: user?.uid.orEmpty() + val identifier = user?.displayIdentifier().orEmpty() Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, @@ -263,7 +264,7 @@ private fun AppAuthenticatedContent( } is AuthState.RequiresEmailVerification -> { - val email = uiContext.authUI.getCurrentUser()?.email ?: stringProvider.emailProvider + val email = uiContext.authUI.getCurrentUser()?.email?.takeIf { it.isNotBlank() } ?: stringProvider.emailProvider Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, 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 5a065400c..ff41085bf 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 @@ -78,6 +78,7 @@ import com.firebase.ui.auth.ui.screens.email.EmailAuthScreen import com.firebase.ui.auth.ui.screens.phone.PhoneAuthScreen import com.firebase.ui.auth.util.EmailLinkPersistenceManager import com.firebase.ui.auth.util.SignInPreferenceManager +import com.firebase.ui.auth.util.displayIdentifier import com.google.firebase.auth.AuthCredential import com.google.firebase.auth.AuthResult import com.google.firebase.auth.MultiFactorResolver @@ -733,7 +734,7 @@ private fun AuthSuccessContent( onManageMfa: () -> Unit, ) { val user = authUI.getCurrentUser() - val userIdentifier = user?.email ?: user?.phoneNumber ?: user?.uid.orEmpty() + val userIdentifier = user?.displayIdentifier().orEmpty() Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, @@ -783,7 +784,7 @@ private fun EmailVerificationContent( onSignOut: () -> Unit, ) { val user = authUI.getCurrentUser() - val emailLabel = user?.email ?: stringProvider.emailProvider + val emailLabel = user?.email?.takeIf { it.isNotBlank() } ?: stringProvider.emailProvider Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, diff --git a/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt b/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt new file mode 100644 index 000000000..ebb2012c7 --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2025 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.firebase.ui.auth.util + +import com.google.firebase.auth.FirebaseUser + +/** + * Returns the best available display identifier for the user, trying each field in order: + * email → phoneNumber → displayName → uid. + * + * Each field is checked for blank (not just null) so that an empty string returned by the + * Firebase SDK falls through to the next candidate rather than being displayed as-is. + * [FirebaseUser.uid] is always non-null and non-blank for a signed-in user, so the result + * is guaranteed to be non-blank. + */ +fun FirebaseUser.displayIdentifier(): String = + email?.takeIf { it.isNotBlank() } + ?: phoneNumber?.takeIf { it.isNotBlank() } + ?: displayName?.takeIf { it.isNotBlank() } + ?: uid From 6a0e1b335989d1a5d88346f970d80a471d1e6984 Mon Sep 17 00:00:00 2001 From: demolaf Date: Wed, 8 Apr 2026 17:06:00 +0100 Subject: [PATCH 2/2] updates --- .../android/demo/HighLevelApiDemoActivity.kt | 5 +++-- .../ui/auth/ui/screens/FirebaseAuthScreen.kt | 5 +++-- .../com/firebase/ui/auth/util/UserUtils.kt | 20 ++++++++++++------- 3 files changed, 19 insertions(+), 11 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 e34af6b50..ff008abcf 100644 --- a/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt +++ b/app/src/main/java/com/firebaseui/android/demo/HighLevelApiDemoActivity.kt @@ -43,6 +43,7 @@ import com.firebase.ui.auth.ui.screens.AuthSuccessUiContext import com.firebase.ui.auth.ui.screens.FirebaseAuthScreen import com.firebase.ui.auth.util.EmailLinkConstants import com.firebase.ui.auth.util.displayIdentifier +import com.firebase.ui.auth.util.getDisplayEmail import com.google.firebase.auth.actionCodeSettings class HighLevelApiDemoActivity : ComponentActivity() { @@ -212,7 +213,7 @@ private fun AppAuthenticatedContent( when (state) { is AuthState.Success -> { val user = uiContext.authUI.getCurrentUser() - val identifier = user?.displayIdentifier().orEmpty() + val identifier = user.displayIdentifier() Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, @@ -264,7 +265,7 @@ private fun AppAuthenticatedContent( } is AuthState.RequiresEmailVerification -> { - val email = uiContext.authUI.getCurrentUser()?.email?.takeIf { it.isNotBlank() } ?: stringProvider.emailProvider + val email = uiContext.authUI.getCurrentUser().getDisplayEmail(stringProvider.emailProvider) Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, 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 ff41085bf..21bb3ee7e 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 @@ -79,6 +79,7 @@ import com.firebase.ui.auth.ui.screens.phone.PhoneAuthScreen import com.firebase.ui.auth.util.EmailLinkPersistenceManager import com.firebase.ui.auth.util.SignInPreferenceManager import com.firebase.ui.auth.util.displayIdentifier +import com.firebase.ui.auth.util.getDisplayEmail import com.google.firebase.auth.AuthCredential import com.google.firebase.auth.AuthResult import com.google.firebase.auth.MultiFactorResolver @@ -734,7 +735,7 @@ private fun AuthSuccessContent( onManageMfa: () -> Unit, ) { val user = authUI.getCurrentUser() - val userIdentifier = user?.displayIdentifier().orEmpty() + val userIdentifier = user.displayIdentifier() Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, @@ -784,7 +785,7 @@ private fun EmailVerificationContent( onSignOut: () -> Unit, ) { val user = authUI.getCurrentUser() - val emailLabel = user?.email?.takeIf { it.isNotBlank() } ?: stringProvider.emailProvider + val emailLabel = user.getDisplayEmail(stringProvider.emailProvider) Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, diff --git a/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt b/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt index ebb2012c7..8e25766e0 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt +++ b/auth/src/main/java/com/firebase/ui/auth/util/UserUtils.kt @@ -22,11 +22,17 @@ import com.google.firebase.auth.FirebaseUser * * Each field is checked for blank (not just null) so that an empty string returned by the * Firebase SDK falls through to the next candidate rather than being displayed as-is. - * [FirebaseUser.uid] is always non-null and non-blank for a signed-in user, so the result - * is guaranteed to be non-blank. + * Returns an empty string if the user is null. */ -fun FirebaseUser.displayIdentifier(): String = - email?.takeIf { it.isNotBlank() } - ?: phoneNumber?.takeIf { it.isNotBlank() } - ?: displayName?.takeIf { it.isNotBlank() } - ?: uid +fun FirebaseUser?.displayIdentifier(): String = + this?.email?.takeIf { it.isNotBlank() } + ?: this?.phoneNumber?.takeIf { it.isNotBlank() } + ?: this?.displayName?.takeIf { it.isNotBlank() } + ?: this?.uid + ?: "" + +/** + * Returns the user's email if it is non-blank, otherwise returns the provided [fallback]. + */ +fun FirebaseUser?.getDisplayEmail(fallback: String): String = + this?.email?.takeIf { it.isNotBlank() } ?: fallback