/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java

https://github.com/firebase/FirebaseUI-Android · Java · 155 lines · 118 code · 13 blank · 24 comment · 12 complexity · e7c0134e7328bccd84deb1cc77e9a65f MD5 · raw file

  1. package com.firebase.ui.auth.viewmodel.email;
  2. import android.app.Application;
  3. import com.firebase.ui.auth.AuthUI;
  4. import com.firebase.ui.auth.IdpResponse;
  5. import com.firebase.ui.auth.data.model.Resource;
  6. import com.firebase.ui.auth.data.model.User;
  7. import com.firebase.ui.auth.data.remote.ProfileMerger;
  8. import com.firebase.ui.auth.util.FirebaseAuthError;
  9. import com.firebase.ui.auth.util.data.AuthOperationManager;
  10. import com.firebase.ui.auth.util.data.TaskFailureLogger;
  11. import com.firebase.ui.auth.viewmodel.SignInViewModelBase;
  12. import com.google.android.gms.tasks.Continuation;
  13. import com.google.android.gms.tasks.OnCompleteListener;
  14. import com.google.android.gms.tasks.OnFailureListener;
  15. import com.google.android.gms.tasks.OnSuccessListener;
  16. import com.google.android.gms.tasks.Task;
  17. import com.google.android.gms.tasks.Tasks;
  18. import com.google.firebase.auth.AuthCredential;
  19. import com.google.firebase.auth.AuthResult;
  20. import com.google.firebase.auth.EmailAuthProvider;
  21. import com.google.firebase.auth.FirebaseAuth;
  22. import com.google.firebase.auth.FirebaseAuthException;
  23. import androidx.annotation.NonNull;
  24. import androidx.annotation.Nullable;
  25. import androidx.annotation.RestrictTo;
  26. /**
  27. * Handles the logic for {@link com.firebase.ui.auth.ui.email.WelcomeBackPasswordPrompt} including
  28. * signing in with email and password, linking other credentials, and saving credentials to
  29. * SmartLock.
  30. */
  31. @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
  32. public class WelcomeBackPasswordHandler extends SignInViewModelBase {
  33. private static final String TAG = "WBPasswordHandler";
  34. private String mPendingPassword;
  35. public WelcomeBackPasswordHandler(Application application) {
  36. super(application);
  37. }
  38. /**
  39. * Kick off the sign-in process.
  40. */
  41. public void startSignIn(@NonNull final String email,
  42. @NonNull final String password,
  43. @NonNull final IdpResponse inputResponse,
  44. @Nullable final AuthCredential credential) {
  45. setResult(Resource.<IdpResponse>forLoading());
  46. // Store the password before signing in so it can be used for later credential building
  47. mPendingPassword = password;
  48. // Build appropriate IDP response based on inputs
  49. final IdpResponse outputResponse;
  50. if (credential == null) {
  51. // New credential for the email provider
  52. outputResponse = new IdpResponse.Builder(
  53. new User.Builder(EmailAuthProvider.PROVIDER_ID, email).build())
  54. .build();
  55. } else {
  56. // New credential for an IDP (Phone or Social)
  57. outputResponse = new IdpResponse.Builder(inputResponse.getUser())
  58. .setPendingCredential(inputResponse.getCredentialForLinking())
  59. .setToken(inputResponse.getIdpToken())
  60. .setSecret(inputResponse.getIdpSecret())
  61. .build();
  62. }
  63. final AuthOperationManager authOperationManager = AuthOperationManager.getInstance();
  64. if (authOperationManager.canUpgradeAnonymous(getAuth(), getArguments())) {
  65. final AuthCredential credToValidate = EmailAuthProvider.getCredential(email, password);
  66. // Check to see if we need to link (for social providers with the same email)
  67. if (AuthUI.SOCIAL_PROVIDERS.contains(inputResponse.getProviderType())) {
  68. // Add the provider to the same account before triggering a merge failure.
  69. authOperationManager.safeLink(credToValidate, credential, getArguments())
  70. .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
  71. @Override
  72. public void onSuccess(AuthResult result) {
  73. handleMergeFailure(credToValidate);
  74. }
  75. })
  76. .addOnFailureListener(new OnFailureListener() {
  77. @Override
  78. public void onFailure(@NonNull Exception e) {
  79. setResult(Resource.<IdpResponse>forFailure(e));
  80. }
  81. });
  82. } else {
  83. // The user has not tried to log in with a federated IDP containing the same email.
  84. // In this case, we just need to verify that the credential they provided is valid.
  85. // No linking is done for non-federated IDPs.
  86. // A merge failure occurs because the account exists and the user is anonymous.
  87. authOperationManager.validateCredential(credToValidate, getArguments())
  88. .addOnCompleteListener(
  89. new OnCompleteListener<AuthResult>() {
  90. @Override
  91. public void onComplete(@NonNull Task<AuthResult> task) {
  92. if (task.isSuccessful()) {
  93. handleMergeFailure(credToValidate);
  94. } else {
  95. setResult(Resource.<IdpResponse>forFailure(task.getException()));
  96. }
  97. }
  98. });
  99. }
  100. } else {
  101. // Kick off the flow including signing in, linking accounts, and saving with SmartLock
  102. getAuth().signInWithEmailAndPassword(email, password)
  103. .continueWithTask(new Continuation<AuthResult, Task<AuthResult>>() {
  104. @Override
  105. public Task<AuthResult> then(@NonNull Task<AuthResult> task) throws Exception {
  106. // Forward task failure by asking for result
  107. AuthResult result = task.getResult(Exception.class);
  108. // Task succeeded, link user if necessary
  109. if (credential == null) {
  110. return Tasks.forResult(result);
  111. } else {
  112. return result.getUser()
  113. .linkWithCredential(credential)
  114. .continueWithTask(new ProfileMerger(outputResponse))
  115. .addOnFailureListener(new TaskFailureLogger(TAG,
  116. "linkWithCredential+merge failed."));
  117. }
  118. }
  119. })
  120. .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
  121. @Override
  122. public void onSuccess(AuthResult result) {
  123. handleSuccess(outputResponse, result);
  124. }
  125. })
  126. .addOnFailureListener(new OnFailureListener() {
  127. @Override
  128. public void onFailure(@NonNull Exception e) {
  129. setResult(Resource.<IdpResponse>forFailure(e));
  130. }
  131. })
  132. .addOnFailureListener(
  133. new TaskFailureLogger(TAG, "signInWithEmailAndPassword failed."));
  134. }
  135. }
  136. /**
  137. * Get the most recent pending password.
  138. */
  139. public String getPendingPassword() {
  140. return mPendingPassword;
  141. }
  142. }