@@ -74,17 +74,22 @@ class AuthProvidersBuilder {
7474/* *
7575 * Enum class to represent all possible providers.
7676 */
77- internal enum class Provider (val id : String , val isSocialProvider : Boolean = false ) {
78- GOOGLE (GoogleAuthProvider .PROVIDER_ID , isSocialProvider = true ),
79- FACEBOOK (FacebookAuthProvider .PROVIDER_ID , isSocialProvider = true ),
80- TWITTER (TwitterAuthProvider .PROVIDER_ID , isSocialProvider = true ),
81- GITHUB (GithubAuthProvider .PROVIDER_ID , isSocialProvider = true ),
82- EMAIL (EmailAuthProvider .PROVIDER_ID ),
83- PHONE (PhoneAuthProvider .PROVIDER_ID ),
84- ANONYMOUS (" anonymous" ),
85- MICROSOFT (" microsoft.com" ),
86- YAHOO (" yahoo.com" ),
87- APPLE (" apple.com" );
77+ internal enum class Provider (
78+ val id : String ,
79+ val providerName : String ,
80+ val isSocialProvider : Boolean = false ,
81+ ) {
82+ GOOGLE (GoogleAuthProvider .PROVIDER_ID , providerName = " Google" , isSocialProvider = true ),
83+ FACEBOOK (FacebookAuthProvider .PROVIDER_ID , providerName = " Facebook" , isSocialProvider = true ),
84+ TWITTER (TwitterAuthProvider .PROVIDER_ID , providerName = " Twitter" , isSocialProvider = true ),
85+ GITHUB (GithubAuthProvider .PROVIDER_ID , providerName = " Github" , isSocialProvider = true ),
86+ EMAIL (EmailAuthProvider .PROVIDER_ID , providerName = " Email" ),
87+ PHONE (PhoneAuthProvider .PROVIDER_ID , providerName = " Phone" ),
88+ ANONYMOUS (" anonymous" , providerName = " Anonymous" ),
89+ MICROSOFT (" microsoft.com" , providerName = " Microsoft" , isSocialProvider = true ),
90+ YAHOO (" yahoo.com" , providerName = " Yahoo" , isSocialProvider = true ),
91+ APPLE (" apple.com" , providerName = " Apple" , isSocialProvider = true ),
92+ LINE (" oidc.line" , providerName = " LINE" , isSocialProvider = true );
8893
8994 companion object {
9095 fun fromId (id : String ): Provider ? {
@@ -93,83 +98,20 @@ internal enum class Provider(val id: String, val isSocialProvider: Boolean = fal
9398 }
9499}
95100
96- /* *
97- * Base abstract class for OAuth authentication providers with common properties.
98- */
99- abstract class OAuthProvider (
100- override val providerId : String ,
101-
102- override val name : String ,
103- open val scopes : List <String > = emptyList(),
104- open val customParameters : Map <String , String > = emptyMap(),
105- ) : AuthProvider(providerId = providerId, name = name)
106-
107101/* *
108102 * Base abstract class for authentication providers.
109103 */
110- abstract class AuthProvider (open val providerId : String , open val name : String ) {
111-
112- companion object {
113- internal fun canUpgradeAnonymous (config : AuthUIConfiguration , auth : FirebaseAuth ): Boolean {
114- val currentUser = auth.currentUser
115- return config.isAnonymousUpgradeEnabled
116- && currentUser != null
117- && currentUser.isAnonymous
118- }
119-
120- /* *
121- * Merges profile information (display name and photo URL) with the current user's profile.
122- *
123- * This method updates the user's profile only if the current profile is incomplete
124- * (missing display name or photo URL). This prevents overwriting existing profile data.
125- *
126- * **Use case:**
127- * After creating a new user account or linking credentials, update the profile with
128- * information from the sign-up form or social provider.
129- *
130- * @param auth The [FirebaseAuth] instance
131- * @param displayName The display name to set (if current is empty)
132- * @param photoUri The photo URL to set (if current is null)
133- *
134- * **Note:** This operation always succeeds to minimize login interruptions.
135- * Failures are logged but don't prevent sign-in completion.
136- */
137- internal suspend fun mergeProfile (
138- auth : FirebaseAuth ,
139- displayName : String? ,
140- photoUri : Uri ? ,
141- ) {
142- try {
143- val currentUser = auth.currentUser ? : return
144-
145- // Only update if current profile is incomplete
146- val currentDisplayName = currentUser.displayName
147- val currentPhotoUrl = currentUser.photoUrl
148-
149- if (! currentDisplayName.isNullOrEmpty() && currentPhotoUrl != null ) {
150- // Profile is complete, no need to update
151- return
152- }
153-
154- // Build profile update with provided values
155- val nameToSet =
156- if (currentDisplayName.isNullOrEmpty()) displayName else currentDisplayName
157- val photoToSet = currentPhotoUrl ? : photoUri
158-
159- if (nameToSet != null || photoToSet != null ) {
160- val profileUpdates = UserProfileChangeRequest .Builder ()
161- .setDisplayName(nameToSet)
162- .setPhotoUri(photoToSet)
163- .build()
104+ abstract class AuthProvider (open val providerId : String , open val providerName : String ) {
105+ /* *
106+ * Base abstract class for OAuth authentication providers with common properties.
107+ */
108+ abstract class OAuth (
109+ override val providerId : String ,
164110
165- currentUser.updateProfile(profileUpdates).await()
166- }
167- } catch (e: Exception ) {
168- // Log error but don't throw - profile update failure shouldn't prevent sign-in
169- Log .e(" AuthProvider.Email" , " Error updating profile" , e)
170- }
171- }
172- }
111+ override val providerName : String ,
112+ open val scopes : List <String > = emptyList(),
113+ open val customParameters : Map <String , String > = emptyMap(),
114+ ) : AuthProvider(providerId = providerId, providerName = providerName)
173115
174116 /* *
175117 * Email/Password authentication provider configuration.
@@ -212,7 +154,7 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
212154 * A list of custom password validation rules.
213155 */
214156 val passwordValidationRules : List <PasswordRule >,
215- ) : AuthProvider(providerId = Provider .EMAIL .id, name = " Email " ) {
157+ ) : AuthProvider(providerId = Provider .EMAIL .id, providerName = Provider . EMAIL .providerName ) {
216158 companion object {
217159 const val SESSION_ID_LENGTH = 10
218160 val KEY_EMAIL = stringPreferencesKey(" com.firebase.ui.auth.data.client.email" )
@@ -338,7 +280,7 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
338280 * Enables instant verification of the phone number. Defaults to true.
339281 */
340282 val isInstantVerificationEnabled : Boolean = true ,
341- ) : AuthProvider(providerId = Provider .PHONE .id, name = " Phone " ) {
283+ ) : AuthProvider(providerId = Provider .PHONE .id, providerName = Provider . PHONE .providerName ) {
342284 /* *
343285 * Sealed class representing the result of phone number verification.
344286 *
@@ -562,9 +504,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
562504 * A map of custom OAuth parameters.
563505 */
564506 override val customParameters : Map <String , String > = emptyMap(),
565- ) : OAuthProvider (
507+ ) : OAuth (
566508 providerId = Provider .GOOGLE .id,
567- name = " Google " ,
509+ providerName = Provider . GOOGLE .providerName ,
568510 scopes = scopes,
569511 customParameters = customParameters
570512 ) {
@@ -691,9 +633,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
691633 * A map of custom OAuth parameters.
692634 */
693635 override val customParameters : Map <String , String > = emptyMap(),
694- ) : OAuthProvider (
636+ ) : OAuth (
695637 providerId = Provider .FACEBOOK .id,
696- name = " Facebook " ,
638+ providerName = Provider . FACEBOOK .providerName ,
697639 scopes = scopes,
698640 customParameters = customParameters
699641 ) {
@@ -835,9 +777,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
835777 * A map of custom OAuth parameters.
836778 */
837779 override val customParameters : Map <String , String >,
838- ) : OAuthProvider (
780+ ) : OAuth (
839781 providerId = Provider .TWITTER .id,
840- name = " Twitter " ,
782+ providerName = Provider . TWITTER .providerName ,
841783 customParameters = customParameters
842784 )
843785
@@ -854,9 +796,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
854796 * A map of custom OAuth parameters.
855797 */
856798 override val customParameters : Map <String , String >,
857- ) : OAuthProvider (
799+ ) : OAuth (
858800 providerId = Provider .GITHUB .id,
859- name = " Github " ,
801+ providerName = Provider . GITHUB .providerName ,
860802 scopes = scopes,
861803 customParameters = customParameters
862804 )
@@ -879,9 +821,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
879821 * A map of custom OAuth parameters.
880822 */
881823 override val customParameters : Map <String , String >,
882- ) : OAuthProvider (
824+ ) : OAuth (
883825 providerId = Provider .MICROSOFT .id,
884- name = " Microsoft " ,
826+ providerName = Provider . MICROSOFT .providerName ,
885827 scopes = scopes,
886828 customParameters = customParameters
887829 )
@@ -899,9 +841,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
899841 * A map of custom OAuth parameters.
900842 */
901843 override val customParameters : Map <String , String >,
902- ) : OAuthProvider (
844+ ) : OAuth (
903845 providerId = Provider .YAHOO .id,
904- name = " Yahoo " ,
846+ providerName = Provider . YAHOO .providerName ,
905847 scopes = scopes,
906848 customParameters = customParameters
907849 )
@@ -924,9 +866,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
924866 * A map of custom OAuth parameters.
925867 */
926868 override val customParameters : Map <String , String >,
927- ) : OAuthProvider (
869+ ) : OAuth (
928870 providerId = Provider .APPLE .id,
929- name = " Apple " ,
871+ providerName = Provider . APPLE .providerName ,
930872 scopes = scopes,
931873 customParameters = customParameters
932874 )
@@ -936,7 +878,7 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
936878 */
937879 object Anonymous : AuthProvider(
938880 providerId = Provider .ANONYMOUS .id,
939- name = " Anonymous "
881+ providerName = Provider . ANONYMOUS .providerName
940882 ) {
941883 internal fun validate (providers : List <AuthProvider >) {
942884 if (providers.size == 1 && providers.first() is Anonymous ) {
@@ -948,14 +890,26 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
948890 }
949891 }
950892
893+ class Line (
894+ override val scopes : List <String >,
895+ override val customParameters : Map <String , String >,
896+ ) : OAuth(
897+ providerId = Provider .LINE .id,
898+ providerName = Provider .LINE .providerName,
899+ scopes = scopes,
900+ customParameters = customParameters
901+ ) {
902+ internal fun validate () {}
903+ }
904+
951905 /* *
952906 * A generic OAuth provider for any unsupported provider.
953907 */
954908 class GenericOAuth (
955909 /* *
956910 * The provider name.
957911 */
958- override val name : String ,
912+ override val providerName : String ,
959913
960914 /* *
961915 * The provider ID as configured in the Firebase console.
@@ -991,9 +945,9 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
991945 * An optional content color for the provider button.
992946 */
993947 val contentColor : Color ? ,
994- ) : OAuthProvider (
948+ ) : OAuth (
995949 providerId = providerId,
996- name = name ,
950+ providerName = providerName ,
997951 scopes = scopes,
998952 customParameters = customParameters
999953 ) {
@@ -1007,4 +961,66 @@ abstract class AuthProvider(open val providerId: String, open val name: String)
1007961 }
1008962 }
1009963 }
964+
965+ companion object {
966+ internal fun canUpgradeAnonymous (config : AuthUIConfiguration , auth : FirebaseAuth ): Boolean {
967+ val currentUser = auth.currentUser
968+ return config.isAnonymousUpgradeEnabled
969+ && currentUser != null
970+ && currentUser.isAnonymous
971+ }
972+
973+ /* *
974+ * Merges profile information (display name and photo URL) with the current user's profile.
975+ *
976+ * This method updates the user's profile only if the current profile is incomplete
977+ * (missing display name or photo URL). This prevents overwriting existing profile data.
978+ *
979+ * **Use case:**
980+ * After creating a new user account or linking credentials, update the profile with
981+ * information from the sign-up form or social provider.
982+ *
983+ * @param auth The [FirebaseAuth] instance
984+ * @param displayName The display name to set (if current is empty)
985+ * @param photoUri The photo URL to set (if current is null)
986+ *
987+ * **Note:** This operation always succeeds to minimize login interruptions.
988+ * Failures are logged but don't prevent sign-in completion.
989+ */
990+ internal suspend fun mergeProfile (
991+ auth : FirebaseAuth ,
992+ displayName : String? ,
993+ photoUri : Uri ? ,
994+ ) {
995+ try {
996+ val currentUser = auth.currentUser ? : return
997+
998+ // Only update if current profile is incomplete
999+ val currentDisplayName = currentUser.displayName
1000+ val currentPhotoUrl = currentUser.photoUrl
1001+
1002+ if (! currentDisplayName.isNullOrEmpty() && currentPhotoUrl != null ) {
1003+ // Profile is complete, no need to update
1004+ return
1005+ }
1006+
1007+ // Build profile update with provided values
1008+ val nameToSet =
1009+ if (currentDisplayName.isNullOrEmpty()) displayName else currentDisplayName
1010+ val photoToSet = currentPhotoUrl ? : photoUri
1011+
1012+ if (nameToSet != null || photoToSet != null ) {
1013+ val profileUpdates = UserProfileChangeRequest .Builder ()
1014+ .setDisplayName(nameToSet)
1015+ .setPhotoUri(photoToSet)
1016+ .build()
1017+
1018+ currentUser.updateProfile(profileUpdates).await()
1019+ }
1020+ } catch (e: Exception ) {
1021+ // Log error but don't throw - profile update failure shouldn't prevent sign-in
1022+ Log .e(" AuthProvider.Email" , " Error updating profile" , e)
1023+ }
1024+ }
1025+ }
10101026}
0 commit comments