From 5f7339a3fe71b5f1cad2a721939fe6c700f6705b Mon Sep 17 00:00:00 2001 From: Ademola Fadumo Date: Mon, 22 Dec 2025 13:01:45 +0100 Subject: [PATCH] fix: initialize serverClientId to default_web_client_id in AuthProvider.Google - The `applicationId` parameter has been removed from the `AuthProvider.Facebook` constructor. Configuration values (`facebook_application_id`, `facebook_login_protocol_scheme`, and `facebook_client_token`) are now exclusively read from `strings.xml`. - The `serverClientId` for the Google provider is now automatically populated from `R.string.default_web_client_id` if it is not explicitly provided. - Added validation to ensure `facebook_client_token` and `facebook_login_protocol_scheme` are configured in `strings.xml`. - Updated tests to use resource files for provider configuration instead of constructor arguments. - Updated `README.md` to reflect the new configuration requirements, including adding `facebook_client_token`. --- auth/README.md | 4 +- .../auth_provider/AuthProvider.kt | 52 +++++++++++-------- .../configuration/AuthUIConfigurationTest.kt | 3 +- .../auth_provider/AuthProviderTest.kt | 37 +++++++------ .../FacebookAuthProviderFirebaseAuthUI.kt | 15 +++--- auth/src/test/res/values-night/config.xml | 7 +++ 6 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 auth/src/test/res/values-night/config.xml diff --git a/auth/README.md b/auth/README.md index ecc3208aa..6061eea06 100644 --- a/auth/README.md +++ b/auth/README.md @@ -138,6 +138,7 @@ If using Facebook Login, add your Facebook App ID to `strings.xml`: YOUR_FACEBOOK_APP_ID fbYOUR_FACEBOOK_APP_ID + CHANGE-ME ``` @@ -489,9 +490,6 @@ Configure Facebook Login with optional permissions: ```kotlin val facebookProvider = AuthProvider.Facebook( - // Optional: Facebook application ID (reads from strings.xml if not provided) - applicationId = "YOUR_FACEBOOK_APP_ID", - // Optional: Permissions to request (default: ["email", "public_profile"]) scopes = listOf("email", "public_profile", "user_friends"), diff --git a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AuthProvider.kt b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AuthProvider.kt index 1b659a8fc..7e552ec0c 100644 --- a/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AuthProvider.kt +++ b/auth/src/main/java/com/firebase/ui/auth/configuration/auth_provider/AuthProvider.kt @@ -485,7 +485,7 @@ abstract class AuthProvider(open val providerId: String, open val providerName: /** * The OAuth 2.0 client ID for your server. */ - val serverClientId: String?, + var serverClientId: String?, /** * A map of custom OAuth parameters. @@ -505,8 +505,9 @@ abstract class AuthProvider(open val providerId: String, open val providerName: " default_web_client_id string wasn't populated.", R.string.default_web_client_id ) + serverClientId = context.getString(R.string.default_web_client_id) } else { - require(serverClientId.isNotBlank()) { + require(serverClientId!!.isNotBlank()) { "Server client ID cannot be blank." } } @@ -529,7 +530,7 @@ abstract class AuthProvider(open val providerId: String, open val providerName: val credential: AuthCredential, val idToken: String, val displayName: String?, - val photoUrl: Uri? + val photoUrl: Uri?, ) /** @@ -567,7 +568,7 @@ abstract class AuthProvider(open val providerId: String, open val providerName: credentialManager: CredentialManager, serverClientId: String, filterByAuthorizedAccounts: Boolean, - autoSelectEnabled: Boolean + autoSelectEnabled: Boolean, ): GoogleSignInResult suspend fun clearCredentialState( @@ -600,8 +601,10 @@ abstract class AuthProvider(open val providerId: String, open val providerName: .build() val result = credentialManager.getCredential(context, request) - val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(result.credential.data) - val credential = GoogleAuthProvider.getCredential(googleIdTokenCredential.idToken, null) + val googleIdTokenCredential = + GoogleIdTokenCredential.createFrom(result.credential.data) + val credential = + GoogleAuthProvider.getCredential(googleIdTokenCredential.idToken, null) return GoogleSignInResult( credential = credential, @@ -624,11 +627,6 @@ abstract class AuthProvider(open val providerId: String, open val providerName: * Facebook Login provider configuration. */ class Facebook( - /** - * The Facebook application ID. - */ - val applicationId: String? = null, - /** * The list of scopes (permissions) to request. Defaults to email and public_profile. */ @@ -653,18 +651,26 @@ abstract class AuthProvider(open val providerId: String, open val providerName: ) } - if (applicationId == null) { - Preconditions.checkConfigured( - context, - "Facebook provider unconfigured. Make sure to " + - "add a `facebook_application_id` string or provide applicationId parameter.", - R.string.facebook_application_id - ) - } else { - require(applicationId.isNotBlank()) { - "Facebook application ID cannot be blank" - } - } + Preconditions.checkConfigured( + context, + "Facebook provider unconfigured. Make sure to " + + "add a `facebook_application_id` string to your strings.xml", + R.string.facebook_application_id + ) + + Preconditions.checkConfigured( + context, + "Facebook provider unconfigured. Make sure to " + + "add a `facebook_login_protocol_scheme` string to your strings.xml", + R.string.facebook_login_protocol_scheme + ) + + Preconditions.checkConfigured( + context, + "Facebook provider unconfigured. Make sure to " + + "add a `facebook_client_token` string to your strings.xml", + R.string.facebook_client_token + ) } /** diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/AuthUIConfigurationTest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/AuthUIConfigurationTest.kt index 80cf85ad6..4afcfa84b 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/AuthUIConfigurationTest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/AuthUIConfigurationTest.kt @@ -294,12 +294,13 @@ class AuthUIConfigurationTest { } @Test + @Config(manifest = Config.NONE, qualifiers = "night") fun `validation accepts all supported providers`() { val config = authUIConfiguration { context = applicationContext providers { provider(AuthProvider.Google(scopes = listOf(), serverClientId = "test_client_id")) - provider(AuthProvider.Facebook(applicationId = "test_app_id")) + provider(AuthProvider.Facebook()) provider(AuthProvider.Twitter(customParameters = mapOf())) provider(AuthProvider.Github(customParameters = mapOf())) provider(AuthProvider.Microsoft(customParameters = mapOf(), tenant = null)) diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AuthProviderTest.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AuthProviderTest.kt index f64bfc2a6..718d38ad3 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AuthProviderTest.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/AuthProviderTest.kt @@ -2,6 +2,7 @@ package com.firebase.ui.auth.configuration.auth_provider import android.content.Context import androidx.test.core.app.ApplicationProvider +import com.firebase.ui.auth.R import com.google.common.truth.Truth.assertThat import com.google.firebase.auth.actionCodeSettings import org.junit.Before @@ -264,32 +265,34 @@ class AuthProviderTest { } } + @Test + @Config(manifest = Config.NONE, qualifiers = "night") + fun `google provider assigns default_web_client_id to serverClientId when null`() { + val provider = AuthProvider.Google( + scopes = listOf("email"), + serverClientId = null + ) + + provider.validate(applicationContext) + + assertThat(provider.serverClientId) + .isEqualTo(applicationContext.getString(R.string.default_web_client_id)) + } + // ============================================================================================= // Facebook Provider Tests // ============================================================================================= @Test + @Config(manifest = Config.NONE, qualifiers = "night") fun `facebook provider with valid configuration should succeed`() { - val provider = AuthProvider.Facebook(applicationId = "application_id") + val provider = AuthProvider.Facebook() provider.validate(applicationContext) } @Test - fun `facebook provider with empty application id throws`() { - val provider = AuthProvider.Facebook(applicationId = "") - - try { - provider.validate(applicationContext) - assertThat(false).isTrue() // Should not reach here - } catch (e: Exception) { - assertThat(e).isInstanceOf(IllegalArgumentException::class.java) - assertThat(e.message).isEqualTo("Facebook application ID cannot be blank") - } - } - - @Test - fun `facebook provider validates facebook_application_id when applicationId is null`() { + fun `facebook provider validates facebook_application_id`() { val provider = AuthProvider.Facebook() try { @@ -299,7 +302,7 @@ class AuthProviderTest { assertThat(e).isInstanceOf(IllegalStateException::class.java) assertThat(e.message).isEqualTo( "Facebook provider unconfigured. Make sure to " + - "add a `facebook_application_id` string or provide applicationId parameter." + "add a `facebook_application_id` string to your strings.xml" ) } } @@ -400,4 +403,4 @@ class AuthProviderTest { assertThat(e.message).isEqualTo("Button label cannot be null or empty") } } -} \ No newline at end of file +} diff --git a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/FacebookAuthProviderFirebaseAuthUI.kt b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/FacebookAuthProviderFirebaseAuthUI.kt index 155de1f82..1e48bae90 100644 --- a/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/FacebookAuthProviderFirebaseAuthUI.kt +++ b/auth/src/test/java/com/firebase/ui/auth/configuration/auth_provider/FacebookAuthProviderFirebaseAuthUI.kt @@ -103,6 +103,7 @@ class FacebookAuthProviderFirebaseAuthUITest { } @Test + @Config(manifest = Config.NONE, qualifiers = "night") fun `signInWithFacebook - successful sign in signs user in and emits Success authState`() = runTest { val authStateListeners = mutableListOf() doAnswer { invocation -> @@ -118,9 +119,7 @@ class FacebookAuthProviderFirebaseAuthUITest { whenever(mockFirebaseAuth.currentUser).thenReturn(null) val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) - val provider = spy(AuthProvider.Facebook( - applicationId = "000000000000" - )) + val provider = spy(AuthProvider.Facebook()) val config = authUIConfiguration { context = applicationContext providers { @@ -175,6 +174,7 @@ class FacebookAuthProviderFirebaseAuthUITest { } @Test + @Config(manifest = Config.NONE, qualifiers = "night") fun `signInWithFacebook - handles account collision by saving credential and emitting error`() = runTest { EmailLinkPersistenceManager.default.clear(applicationContext) EmailLinkPersistenceManager.default.saveEmail( @@ -185,9 +185,7 @@ class FacebookAuthProviderFirebaseAuthUITest { ) val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) - val provider = spy(AuthProvider.Facebook( - applicationId = "000000000000" - )) + val provider = spy(AuthProvider.Facebook()) val config = authUIConfiguration { context = applicationContext providers { @@ -238,11 +236,10 @@ class FacebookAuthProviderFirebaseAuthUITest { } @Test + @Config(manifest = Config.NONE, qualifiers = "night") fun `signInWithFacebook - converts FacebookException into AuthException`() = runTest { val instance = FirebaseAuthUI.create(firebaseApp, mockFirebaseAuth) - val provider = spy(AuthProvider.Facebook( - applicationId = "000000000000" - )) + val provider = spy(AuthProvider.Facebook()) val config = authUIConfiguration { context = applicationContext providers { diff --git a/auth/src/test/res/values-night/config.xml b/auth/src/test/res/values-night/config.xml new file mode 100644 index 000000000..0b31fe015 --- /dev/null +++ b/auth/src/test/res/values-night/config.xml @@ -0,0 +1,7 @@ + + + test_client_id + test_app_id + test_login_scheme + test_client_token +