14
14
15
15
package com.firebase.ui.auth.compose.configuration
16
16
17
+ import android.content.Context
17
18
import android.graphics.Color
19
+ import android.util.Log
18
20
import 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
19
26
import com.google.firebase.auth.ActionCodeSettings
20
27
import com.google.firebase.auth.EmailAuthProvider
21
28
import com.google.firebase.auth.FacebookAuthProvider
@@ -78,6 +85,14 @@ abstract class AuthProvider(open val providerId: String) {
78
85
*/
79
86
val isEmailLinkSignInEnabled : Boolean = false ,
80
87
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
+ val isEmailLinkForceSameDeviceEnabled : Boolean = true ,
95
+
81
96
/* *
82
97
* Settings for email link actions.
83
98
*/
@@ -100,11 +115,10 @@ abstract class AuthProvider(open val providerId: String) {
100
115
) : AuthProvider(providerId = Provider .EMAIL .id) {
101
116
fun validate () {
102
117
if (isEmailLinkSignInEnabled) {
103
- val actionCodeSettings = actionCodeSettings
104
- ? : requireNotNull(actionCodeSettings) {
105
- " ActionCodeSettings cannot be null when using " +
106
- " email link sign in."
107
- }
118
+ val actionCodeSettings = requireNotNull(actionCodeSettings) {
119
+ " ActionCodeSettings cannot be null when using " +
120
+ " email link sign in."
121
+ }
108
122
109
123
check(actionCodeSettings.canHandleCodeInApp()) {
110
124
" You must set canHandleCodeInApp in your " +
@@ -118,6 +132,11 @@ abstract class AuthProvider(open val providerId: String) {
118
132
* Phone number authentication provider configuration.
119
133
*/
120
134
class Phone (
135
+ /* *
136
+ * The phone number in international format.
137
+ */
138
+ val defaultNumber : String? ,
139
+
121
140
/* *
122
141
* The default country code to pre-select.
123
142
*/
@@ -147,7 +166,31 @@ abstract class AuthProvider(open val providerId: String) {
147
166
* Enables automatic retrieval of the SMS code. Defaults to true.
148
167
*/
149
168
val isAutoRetrievalEnabled : Boolean = true
150
- ) : AuthProvider(providerId = Provider .PHONE .id)
169
+ ) : AuthProvider(providerId = Provider .PHONE .id) {
170
+ fun validate () {
171
+ defaultNumber?.let {
172
+ check(PhoneNumberUtils .isValid(it)) {
173
+ " Invalid phone number: $it "
174
+ }
175
+ }
176
+
177
+ defaultCountryCode?.let {
178
+ check(PhoneNumberUtils .isValidIso(it)) {
179
+ " Invalid country iso: $it "
180
+ }
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
+ }
151
194
152
195
/* *
153
196
* Google Sign-In provider configuration.
@@ -186,12 +229,40 @@ abstract class AuthProvider(open val providerId: String) {
186
229
providerId = Provider .GOOGLE .id,
187
230
scopes = scopes,
188
231
customParameters = customParameters
189
- )
232
+ ) {
233
+ fun validate (context : Context ) {
234
+ if (serverClientId == null ) {
235
+ Preconditions .checkConfigured(
236
+ context,
237
+ " Check your google-services plugin configuration, the" +
238
+ " default_web_client_id string wasn't populated." ,
239
+ R .string.default_web_client_id
240
+ )
241
+ } else {
242
+ require(serverClientId.isNotBlank()) {
243
+ " Server client ID cannot be blank."
244
+ }
245
+ }
246
+
247
+ val hasEmailScope = scopes.contains(" email" )
248
+ if (! hasEmailScope) {
249
+ Log .w(
250
+ " AuthProvider.Google" ,
251
+ " The scopes do not include 'email'. In most cases this is a mistake!"
252
+ )
253
+ }
254
+ }
255
+ }
190
256
191
257
/* *
192
258
* Facebook Login provider configuration.
193
259
*/
194
260
class Facebook (
261
+ /* *
262
+ * The Facebook application ID.
263
+ */
264
+ val applicationId : String? = null ,
265
+
195
266
/* *
196
267
* The list of scopes (permissions) to request. Defaults to email and public_profile.
197
268
*/
@@ -210,7 +281,30 @@ abstract class AuthProvider(open val providerId: String) {
210
281
providerId = Provider .FACEBOOK .id,
211
282
scopes = scopes,
212
283
customParameters = customParameters
213
- )
284
+ ) {
285
+ fun validate (context : Context ) {
286
+ if (! ProviderAvailability .IS_FACEBOOK_AVAILABLE ) {
287
+ throw RuntimeException (
288
+ " Facebook provider cannot be configured " +
289
+ " without dependency. Did you forget to add " +
290
+ " 'com.facebook.android:facebook-login:VERSION' dependency?"
291
+ )
292
+ }
293
+
294
+ if (applicationId == null ) {
295
+ Preconditions .checkConfigured(
296
+ context,
297
+ " Facebook provider unconfigured. Make sure to " +
298
+ " add a `facebook_application_id` string or provide applicationId parameter." ,
299
+ R .string.facebook_application_id
300
+ )
301
+ } else {
302
+ require(applicationId.isNotBlank()) {
303
+ " Facebook application ID cannot be blank"
304
+ }
305
+ }
306
+ }
307
+ }
214
308
215
309
/* *
216
310
* Twitter/X authentication provider configuration.
@@ -314,7 +408,16 @@ abstract class AuthProvider(open val providerId: String) {
314
408
/* *
315
409
* Anonymous authentication provider. It has no configurable properties.
316
410
*/
317
- object Anonymous : AuthProvider(providerId = Provider .ANONYMOUS .id)
411
+ object Anonymous : AuthProvider(providerId = Provider .ANONYMOUS .id) {
412
+ fun validate (providers : List <AuthProvider >) {
413
+ if (providers.size == 1 && providers.first() is Anonymous ) {
414
+ throw IllegalStateException (
415
+ " Sign in as guest cannot be the only sign in method. " +
416
+ " In this case, sign the user in anonymously your self; no UI is needed."
417
+ )
418
+ }
419
+ }
420
+ }
318
421
319
422
/* *
320
423
* A generic OAuth provider for any unsupported provider.
@@ -353,5 +456,15 @@ abstract class AuthProvider(open val providerId: String) {
353
456
providerId = providerId,
354
457
scopes = scopes,
355
458
customParameters = customParameters
356
- )
459
+ ) {
460
+ fun validate () {
461
+ require(providerId.isNotBlank()) {
462
+ " Provider ID cannot be null or empty"
463
+ }
464
+
465
+ require(buttonLabel.isNotBlank()) {
466
+ " Button label cannot be null or empty"
467
+ }
468
+ }
469
+ }
357
470
}
0 commit comments