3232import com .firebase .ui .auth .util .data .PhoneNumberUtils ;
3333import com .firebase .ui .auth .util .data .ProviderAvailability ;
3434import com .firebase .ui .auth .util .data .ProviderUtils ;
35- import com .google .android .gms .auth .api .credentials .Credential ;
36- import com .google .android .gms .auth .api .credentials .CredentialRequest ;
37- import com .google .android .gms .auth .api .credentials .CredentialsClient ;
38- import com .google .android .gms .auth .api .signin .GoogleSignIn ;
39- import com .google .android .gms .auth .api .signin .GoogleSignInAccount ;
40- import com .google .android .gms .auth .api .signin .GoogleSignInOptions ;
41- import com .google .android .gms .common .api .ApiException ;
42- import com .google .android .gms .common .api .CommonStatusCodes ;
43- import com .google .android .gms .common .api .Scope ;
35+
4436import com .google .android .gms .tasks .Task ;
4537import com .google .android .gms .tasks .Tasks ;
4638import com .google .firebase .FirebaseApp ;
7870import androidx .annotation .Nullable ;
7971import androidx .annotation .RestrictTo ;
8072import androidx .annotation .StringDef ;
73+ import androidx .credentials .Credential ;
74+ import androidx .credentials .PasswordCredential ;
75+ import androidx .credentials .CredentialManager ;
76+ import androidx .credentials .exceptions .NoCredentialsException ;
77+ import androidx .credentials .exceptions .CredentialException ;
78+ import androidx .credentials .exceptions .GetCredentialException ;
79+ import androidx .credentials .exceptions .CreateCredentialException ;
80+ import androidx .credentials .exceptions .BeginCreateCredentialException ;
81+ import androidx .credentials .exceptions .CreateCredentialCustomizationException ;
82+ import android .widget .Toast ;
8183import androidx .annotation .StyleRes ;
8284
85+
8386/**
8487 * The entry point to the AuthUI authentication flow, and related utility methods. If your
8588 * application uses the default {@link FirebaseApp} instance, an AuthUI instance can be retrieved
@@ -269,33 +272,7 @@ public static int getDefaultTheme() {
269272 return R .style .FirebaseUI_DefaultMaterialTheme ;
270273 }
271274
272- /**
273- * Make a list of {@link Credential} from a FirebaseUser. Useful for deleting Credentials, not
274- * for saving since we don't have access to the password.
275- */
276- private static List <Credential > getCredentialsFromFirebaseUser (@ NonNull FirebaseUser user ) {
277- if (TextUtils .isEmpty (user .getEmail ()) && TextUtils .isEmpty (user .getPhoneNumber ())) {
278- return Collections .emptyList ();
279- }
280275
281- List <Credential > credentials = new ArrayList <>();
282- for (UserInfo userInfo : user .getProviderData ()) {
283- if (FirebaseAuthProvider .PROVIDER_ID .equals (userInfo .getProviderId ())) {
284- continue ;
285- }
286-
287- String type = ProviderUtils .providerIdToAccountType (userInfo .getProviderId ());
288- if (type == null ) {
289- // Since the account type is null, we've got an email credential. Adding a fake
290- // password is the only way to tell Smart Lock that this is an email credential.
291- credentials .add (CredentialUtils .buildCredentialOrThrow (user , "pass" , null ));
292- } else {
293- credentials .add (CredentialUtils .buildCredentialOrThrow (user , null , type ));
294- }
295- }
296-
297- return credentials ;
298- }
299276
300277 /**
301278 * Signs the user in without any UI if possible. If this operation fails, you can safely start a
@@ -344,38 +321,12 @@ public Task<AuthResult> silentSignIn(@NonNull Context context,
344321 new FirebaseUiException (ErrorCodes .PLAY_SERVICES_UPDATE_CANCELLED ));
345322 }
346323
347- return GoogleApiUtils .getCredentialsClient (context )
348- .request (new CredentialRequest .Builder ()
349- // We can support both email and Google at the same time here because they
350- // are mutually exclusive. If a user signs in with Google, their email
351- // account will automatically be upgraded (a.k.a. replaced) with the Google
352- // one, meaning Smart Lock won't have to show the picker UI.
353- .setPasswordLoginSupported (email != null )
354- .setAccountTypes (google == null ? null :
355- ProviderUtils .providerIdToAccountType (GoogleAuthProvider
356- .PROVIDER_ID ))
357- .build ())
358- .continueWithTask (task -> {
359- Credential credential = task .getResult ().getCredential ();
360- String email1 = credential .getId ();
361- String password = credential .getPassword ();
362-
363- if (TextUtils .isEmpty (password )) {
364- return GoogleSignIn .getClient (appContext ,
365- new GoogleSignInOptions .Builder (googleOptions )
366- .setAccountName (email1 )
367- .build ())
368- .silentSignIn ()
369- .continueWithTask (task1 -> {
370- AuthCredential authCredential = GoogleAuthProvider
371- .getCredential (
372- task1 .getResult ().getIdToken (), null );
373- return mAuth .signInWithCredential (authCredential );
374- });
375- } else {
376- return mAuth .signInWithEmailAndPassword (email1 , password );
377- }
378- });
324+ // If Play services are not available we can't attempt to use the credentials client.
325+ if (!GoogleApiUtils .isPlayServicesAvailable (context )) {
326+ return Tasks .forException (
327+ new FirebaseUiException (ErrorCodes .PLAY_SERVICES_UPDATE_CANCELLED ));
328+ }
329+ return Tasks .forException (new Exception ("Not implemented yet" ));
379330 }
380331
381332 /**
@@ -393,36 +344,21 @@ public Task<Void> signOut(@NonNull Context context) {
393344 Log .w (TAG , "Google Play services not available during signOut" );
394345 }
395346
396- Task <Void > maybeDisableAutoSignIn = playServicesAvailable
397- ? GoogleApiUtils .getCredentialsClient (context ).disableAutoSignIn ()
398- : Tasks .forResult ((Void ) null );
399-
400- maybeDisableAutoSignIn
401- .continueWith (task -> {
402- // We want to ignore a specific exception, since it's not a good reason
403- // to fail (see Issue 1156).
404- Exception e = task .getException ();
405- if (e instanceof ApiException
406- && ((ApiException ) e ).getStatusCode () == CommonStatusCodes
407- .CANCELED ) {
408- Log .w (TAG , "Could not disable auto-sign in, maybe there are no " +
409- "SmartLock accounts available?" , e );
410- return null ;
411- }
412-
413- return task .getResult ();
414- });
347+ boolean playServicesAvailable = GoogleApiUtils .isPlayServicesAvailable (context );
348+ if (!playServicesAvailable ) {
349+ Log .w (TAG , "Google Play services not available during signOut" );
350+ }
415351
416352 return Tasks .whenAll (
417- signOutIdps (context ),
418- maybeDisableAutoSignIn
353+ signOutIdps (context )
419354 ).continueWith (task -> {
420355 task .getResult (); // Propagate exceptions
421356 mAuth .signOut ();
422357 return null ;
423358 });
424359 }
425360
361+
426362 /**
427363 * Delete the use from FirebaseAuth and delete any associated credentials from the Credentials
428364 * API. Returns a {@link Task} that succeeds if the Firebase Auth user deletion succeeds and
@@ -432,6 +368,36 @@ public Task<Void> signOut(@NonNull Context context) {
432368 * @param context the calling {@link Context}.
433369 */
434370 @ NonNull
371+ public Task <Void > delete (@ NonNull final Context context ) {
372+ final FirebaseUser currentUser = mAuth .getCurrentUser ();
373+ if (currentUser == null ) {
374+ return Tasks .forException (new FirebaseAuthInvalidUserException (
375+ String .valueOf (CommonStatusCodes .SIGN_IN_REQUIRED ),
376+ "No currently signed in user." ));
377+ }
378+
379+ // Ensure the order in which tasks are executed properly destructures the user.
380+ return signOutIdps (context ).continueWithTask (task -> {
381+ task .getResult (); // Propagate exception if there was one
382+
383+ if (!GoogleApiUtils .isPlayServicesAvailable (context )) {
384+ Log .w (TAG , "Google Play services not available during delete" );
385+ return Tasks .forResult ((Void ) null );
386+ }
387+ }).continueWithTask (task -> {
388+ task .getResult (); // Propagate exception if there was one
389+ return currentUser .delete ();
390+ });
391+ }
392+ /**
393+ * Delete the use from FirebaseAuth and delete any associated credentials from the Credentials
394+ * API. Returns a {@link Task} that succeeds if the Firebase Auth user deletion succeeds and
395+ * fails if the Firebase Auth deletion fails. Credentials deletion failures are handled
396+ * silently.
397+ *
398+ * @param context the calling {@link Context}.
399+ */
400+ @ NonNull
435401 public Task <Void > delete (@ NonNull final Context context ) {
436402 final FirebaseUser currentUser = mAuth .getCurrentUser ();
437403 if (currentUser == null ) {
@@ -1293,8 +1259,6 @@ private abstract class AuthIntentBuilder<T extends AuthIntentBuilder> {
12931259 String mPrivacyPolicyUrl ;
12941260 boolean mAlwaysShowProviderChoice = false ;
12951261 boolean mLockOrientation = false ;
1296- boolean mEnableCredentials = true ;
1297- boolean mEnableHints = true ;
12981262 AuthMethodPickerLayout mAuthMethodPickerLayout = null ;
12991263 ActionCodeSettings mPasswordSettings = null ;
13001264
@@ -1441,12 +1405,7 @@ public T setIsSmartLockEnabled(boolean enabled) {
14411405 * @param enableCredentials enables credential selector before signup
14421406 * @param enableHints enable hint selector in respective signup screens
14431407 */
1444- @ NonNull
1445- public T setIsSmartLockEnabled (boolean enableCredentials , boolean enableHints ) {
1446- mEnableCredentials = enableCredentials ;
1447- mEnableHints = enableHints ;
1448- return (T ) this ;
1449- }
1408+
14501409
14511410 /**
14521411 * Set a custom layout for the AuthMethodPickerActivity screen.
@@ -1576,9 +1535,6 @@ protected FlowParameters getFlowParams() {
15761535 mLogo ,
15771536 mTosUrl ,
15781537 mPrivacyPolicyUrl ,
1579- mEnableCredentials ,
1580- mEnableHints ,
1581- mEnableAnonymousUpgrade ,
15821538 mAlwaysShowProviderChoice ,
15831539 mLockOrientation ,
15841540 mEmailLink ,
0 commit comments