Skip to content

Commit 88c52da

Browse files
SUPERCILEXsamtstern
authored andcommitted
Fix email and Google providers creating duplicate credentials (#1229)
1 parent 032df2b commit 88c52da

File tree

10 files changed

+143
-150
lines changed

10 files changed

+143
-150
lines changed

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.firebase.ui.auth.data.remote.FacebookSignInHandler;
3535
import com.firebase.ui.auth.data.remote.TwitterSignInHandler;
3636
import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity;
37+
import com.firebase.ui.auth.util.CredentialUtils;
3738
import com.firebase.ui.auth.util.ExtraConstants;
3839
import com.firebase.ui.auth.util.GoogleApiUtils;
3940
import com.firebase.ui.auth.util.Preconditions;
@@ -392,11 +393,13 @@ private static List<Credential> getCredentialsFromFirebaseUser(@NonNull Firebase
392393
}
393394

394395
String type = ProviderUtils.providerIdToAccountType(userInfo.getProviderId());
395-
396-
credentials.add(new Credential.Builder(
397-
TextUtils.isEmpty(user.getEmail()) ? user.getPhoneNumber() : user.getEmail())
398-
.setAccountType(type)
399-
.build());
396+
if (type == null) {
397+
// Since the account type is null, we've got an email credential. Adding a fake
398+
// password is the only way to tell Smart Lock that this is an email credential.
399+
credentials.add(CredentialUtils.buildCredentialOrThrow(user, "pass", null));
400+
} else {
401+
credentials.add(CredentialUtils.buildCredentialOrThrow(user, null, type));
402+
}
400403
}
401404

402405
return credentials;
@@ -631,8 +634,8 @@ public EmailBuilder setAllowNewAccounts(boolean allow) {
631634
}
632635

633636
/**
634-
* Configures the requirement for the user to enter first and last name
635-
* in the email sign up flow.
637+
* Configures the requirement for the user to enter first and last name in the email
638+
* sign up flow.
636639
* <p>
637640
* Name is required by default.
638641
*/

auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,6 @@ private Resource(State state, T value, Exception exception) {
2424
mException = exception;
2525
}
2626

27-
/**
28-
* Creates a successful, empty Resource.
29-
*/
30-
@NonNull
31-
public static Resource<Void> forVoidSuccess() {
32-
return new Resource<>(State.SUCCESS, null, null);
33-
}
34-
3527
/**
3628
* Creates a successful resource containing a value.
3729
*/

auth/src/main/java/com/firebase/ui/auth/data/remote/SignInKickstarter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ private void handleCredential(final Credential credential) {
192192
final IdpResponse response = new IdpResponse.Builder(
193193
new User.Builder(EmailAuthProvider.PROVIDER_ID, id).build()).build();
194194

195+
setResult(Resource.<IdpResponse>forLoading());
195196
getAuth().signInWithEmailAndPassword(id, password)
196197
.addOnSuccessListener(new OnSuccessListener<AuthResult>() {
197198
@Override

auth/src/main/java/com/firebase/ui/auth/ui/HelperActivityBase.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import com.firebase.ui.auth.data.model.FlowParameters;
1414
import com.firebase.ui.auth.ui.credentials.CredentialSaveActivity;
1515
import com.firebase.ui.auth.util.AuthHelper;
16-
import com.firebase.ui.auth.util.CredentialsUtil;
16+
import com.firebase.ui.auth.util.CredentialUtils;
1717
import com.firebase.ui.auth.util.ExtraConstants;
1818
import com.firebase.ui.auth.util.data.ProviderUtils;
1919
import com.firebase.ui.auth.viewmodel.RequestCodes;
@@ -59,7 +59,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
5959
super.onActivityResult(requestCode, resultCode, data);
6060
// Forward the results of Smart Lock saving
6161
if (requestCode == RequestCodes.CRED_SAVE_FLOW) {
62-
finish(RESULT_OK, data);
62+
finish(resultCode, data);
6363
}
6464
}
6565

@@ -89,7 +89,7 @@ public void startSaveCredentials(
8989
@Nullable String password) {
9090
// Build credential
9191
String accountType = ProviderUtils.idpResponseToAccountType(response);
92-
Credential credential = CredentialsUtil.buildCredential(
92+
Credential credential = CredentialUtils.buildCredential(
9393
firebaseUser, password, accountType);
9494

9595
// Start the dedicated SmartLock Activity

auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import com.firebase.ui.auth.data.model.Resource;
1515
import com.firebase.ui.auth.ui.HelperActivityBase;
1616
import com.firebase.ui.auth.util.ExtraConstants;
17-
import com.firebase.ui.auth.viewmodel.VoidResourceObserver;
17+
import com.firebase.ui.auth.viewmodel.ResourceObserver;
1818
import com.firebase.ui.auth.viewmodel.smartlock.SmartLockHandler;
1919
import com.google.android.gms.auth.api.credentials.Credential;
2020

@@ -25,7 +25,6 @@ public class CredentialSaveActivity extends HelperActivityBase {
2525
private static final String TAG = "CredentialSaveActivity";
2626

2727
private SmartLockHandler mHandler;
28-
private IdpResponse mIdpResponse;
2928

3029
@NonNull
3130
public static Intent createIntent(Context context,
@@ -41,29 +40,30 @@ public static Intent createIntent(Context context,
4140
protected void onCreate(@Nullable Bundle savedInstanceState) {
4241
super.onCreate(savedInstanceState);
4342

43+
final IdpResponse response = getIntent().getParcelableExtra(ExtraConstants.IDP_RESPONSE);
44+
Credential credential = getIntent().getParcelableExtra(ExtraConstants.CREDENTIAL);
45+
4446
mHandler = ViewModelProviders.of(this).get(SmartLockHandler.class);
4547
mHandler.init(getFlowParams());
48+
mHandler.setResponse(response);
4649

47-
Credential credential = getIntent().getParcelableExtra(ExtraConstants.CREDENTIAL);
48-
mIdpResponse = getIntent().getParcelableExtra(ExtraConstants.IDP_RESPONSE);
49-
50-
mHandler.getOperation().observe(this, new VoidResourceObserver(
50+
mHandler.getOperation().observe(this, new ResourceObserver<IdpResponse>(
5151
this, R.string.fui_progress_dialog_loading) {
5252
@Override
53-
protected void onSuccess() {
54-
finish(RESULT_OK, mIdpResponse.toIntent());
53+
protected void onSuccess(@NonNull IdpResponse response) {
54+
finish(RESULT_OK, response.toIntent());
5555
}
5656

5757
@Override
5858
protected void onFailure(@NonNull Exception e) {
5959
// RESULT_OK since we don't want to halt sign-in just because of a credential save
6060
// error.
61-
finish(RESULT_OK, mIdpResponse.toIntent());
61+
finish(RESULT_OK, response.toIntent());
6262
}
6363
});
6464

6565
// Avoid double-saving
66-
Resource<Void> currentOp = mHandler.getOperation().getValue();
66+
Resource<IdpResponse> currentOp = mHandler.getOperation().getValue();
6767
if (currentOp == null) {
6868
Log.d(TAG, "Launching save operation.");
6969
mHandler.saveCredentials(credential);
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.firebase.ui.auth.util;
2+
3+
import android.net.Uri;
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
import android.support.annotation.RestrictTo;
7+
import android.text.TextUtils;
8+
9+
import com.firebase.ui.auth.IdpResponse;
10+
import com.google.android.gms.auth.api.credentials.Credential;
11+
import com.google.firebase.auth.FirebaseUser;
12+
13+
/**
14+
* Utility class for working with {@link Credential} objects.
15+
*/
16+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
17+
public class CredentialUtils {
18+
private CredentialUtils() {
19+
throw new AssertionError("No instance for you!");
20+
}
21+
22+
/**
23+
* Build a credential for the specified {@link FirebaseUser} with optional password and {@link
24+
* IdpResponse}.
25+
* <p>
26+
* If the credential cannot be built (for example, empty email) then will return {@code null}.
27+
*/
28+
@Nullable
29+
public static Credential buildCredential(@NonNull FirebaseUser user,
30+
@Nullable String password,
31+
@Nullable String accountType) {
32+
String email = user.getEmail();
33+
String phone = user.getPhoneNumber();
34+
Uri profilePictureUri =
35+
user.getPhotoUrl() == null ? null : Uri.parse(user.getPhotoUrl().toString());
36+
37+
if (TextUtils.isEmpty(email) && TextUtils.isEmpty(phone)) { return null; }
38+
if (password == null && accountType == null) { return null; }
39+
40+
Credential.Builder builder =
41+
new Credential.Builder(TextUtils.isEmpty(email) ? phone : email)
42+
.setName(user.getDisplayName())
43+
.setProfilePictureUri(profilePictureUri);
44+
45+
if (TextUtils.isEmpty(password)) {
46+
builder.setAccountType(accountType);
47+
} else {
48+
builder.setPassword(password);
49+
}
50+
51+
return builder.build();
52+
}
53+
54+
/**
55+
* @see #buildCredential(FirebaseUser, String, String)
56+
*/
57+
@NonNull
58+
public static Credential buildCredentialOrThrow(@NonNull FirebaseUser user,
59+
@Nullable String password,
60+
@Nullable String accountType) {
61+
Credential credential = buildCredential(user, password, accountType);
62+
if (credential == null) {
63+
throw new IllegalStateException("Unable to build credential");
64+
}
65+
return credential;
66+
}
67+
}

auth/src/main/java/com/firebase/ui/auth/util/CredentialsUtil.java

Lines changed: 0 additions & 77 deletions
This file was deleted.

auth/src/main/java/com/firebase/ui/auth/viewmodel/VoidResourceObserver.java

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)