1414
1515package com.firebase.ui.auth.compose.configuration
1616
17+ import android.content.Context
1718import android.graphics.Color
19+ import android.util.Log
1820import androidx.compose.ui.graphics.vector.ImageVector
21+ import com.firebase.ui.auth.AuthUI
22+ import com.firebase.ui.auth.R
23+ import com.firebase.ui.auth.util.Preconditions
24+ import com.firebase.ui.auth.util.data.PhoneNumberUtils
25+ import com.firebase.ui.auth.util.data.ProviderAvailability
1926import com.google.firebase.auth.ActionCodeSettings
2027import com.google.firebase.auth.EmailAuthProvider
2128import com.google.firebase.auth.FacebookAuthProvider
@@ -78,6 +85,15 @@ abstract class AuthProvider(open val providerId: String) {
7885 */
7986 val isEmailLinkSignInEnabled : Boolean = false ,
8087
88+ /* *
89+ * Forces email link sign-in to complete on the same device that initiated it.
90+ *
91+ * When enabled, prevents email links from being opened on different devices,
92+ * which is required for security when upgrading anonymous users. Defaults to true.
93+ */
94+
95+ val isEmailLinkForceSameDeviceEnabled : Boolean = true ,
96+
8197 /* *
8298 * Settings for email link actions.
8399 */
@@ -118,6 +134,11 @@ abstract class AuthProvider(open val providerId: String) {
118134 * Phone number authentication provider configuration.
119135 */
120136 class Phone (
137+ /* *
138+ * The phone number in international format.
139+ */
140+ val defaultNumber : String? ,
141+
121142 /* *
122143 * The default country code to pre-select.
123144 */
@@ -147,7 +168,29 @@ abstract class AuthProvider(open val providerId: String) {
147168 * Enables automatic retrieval of the SMS code. Defaults to true.
148169 */
149170 val isAutoRetrievalEnabled : Boolean = true
150- ) : AuthProvider(providerId = Provider .PHONE .id)
171+ ) : AuthProvider(providerId = Provider .PHONE .id) {
172+ fun validate () {
173+ defaultNumber?.let {
174+ check(PhoneNumberUtils .isValid(it)) {
175+ " Invalid phone number: $it "
176+ }
177+ }
178+
179+ check(PhoneNumberUtils .isValidIso(defaultCountryCode)) {
180+ " Invalid country iso: $defaultCountryCode "
181+ }
182+
183+ allowedCountries?.forEach { code ->
184+ check(
185+ PhoneNumberUtils .isValidIso(code) ||
186+ PhoneNumberUtils .isValid(code)
187+ ) {
188+ " Invalid input: You must provide a valid country iso (alpha-2) " +
189+ " or code (e-164). e.g. 'us' or '+1'. Invalid code: $code "
190+ }
191+ }
192+ }
193+ }
151194
152195 /* *
153196 * Google Sign-In provider configuration.
@@ -186,7 +229,30 @@ abstract class AuthProvider(open val providerId: String) {
186229 providerId = Provider .GOOGLE .id,
187230 scopes = scopes,
188231 customParameters = customParameters
189- )
232+ ) {
233+ fun validate (context : Context ) {
234+ // TODO(demolaf): do we need this? since we are requesting this in AuthProvider.Google?
235+ // if serverClientId is nullable do we still need to throw an IllegalStateException?
236+ Preconditions .checkConfigured(
237+ context,
238+ " Check your google-services plugin configuration, the" +
239+ " default_web_client_id string wasn't populated." ,
240+ R .string.default_web_client_id
241+ )
242+
243+ for (scope in scopes) {
244+ if (" email" == scope) {
245+ Log .w(
246+ " AuthProvider.Google" ,
247+ " The GoogleSignInOptions passed to setSignInOptions does not " +
248+ " request the 'email' scope. In most cases this is a mistake! " +
249+ " Call requestEmail() on the GoogleSignInOptions object."
250+ )
251+ break
252+ }
253+ }
254+ }
255+ }
190256
191257 /* *
192258 * Facebook Login provider configuration.
@@ -210,7 +276,26 @@ abstract class AuthProvider(open val providerId: String) {
210276 providerId = Provider .FACEBOOK .id,
211277 scopes = scopes,
212278 customParameters = customParameters
213- )
279+ ) {
280+ fun validate (context : Context ) {
281+ if (ProviderAvailability .IS_FACEBOOK_AVAILABLE ) {
282+ throw RuntimeException (
283+ " Facebook provider cannot be configured " +
284+ " without dependency. Did you forget to add " +
285+ " 'com.facebook.android:facebook-login:VERSION' dependency?"
286+ )
287+ }
288+
289+ // TODO(demolaf): is this required? or should we add appId to AuthProvider.Facebook
290+ // parameters above?
291+ Preconditions .checkConfigured(
292+ context,
293+ " Facebook provider unconfigured. Make sure to " +
294+ " add a `facebook_application_id` string." ,
295+ R .string.facebook_application_id
296+ )
297+ }
298+ }
214299
215300 /* *
216301 * Twitter/X authentication provider configuration.
@@ -314,7 +399,16 @@ abstract class AuthProvider(open val providerId: String) {
314399 /* *
315400 * Anonymous authentication provider. It has no configurable properties.
316401 */
317- object Anonymous : AuthProvider(providerId = Provider .ANONYMOUS .id)
402+ object Anonymous : AuthProvider(providerId = Provider .ANONYMOUS .id) {
403+ fun validate (providers : List <AuthProvider >) {
404+ if (providers.size == 1 && providers.first() is Anonymous ) {
405+ throw IllegalStateException (
406+ " Sign in as guest cannot be the only sign in method. " +
407+ " In this case, sign the user in anonymously your self; no UI is needed."
408+ )
409+ }
410+ }
411+ }
318412
319413 /* *
320414 * A generic OAuth provider for any unsupported provider.
0 commit comments