Skip to content

Commit a55d472

Browse files
Aaron MandleGerrit Code Review
authored andcommitted
Merge "Fix account linking with Facebook"
2 parents da44cc6 + 5901a76 commit a55d472

File tree

8 files changed

+145
-59
lines changed

8 files changed

+145
-59
lines changed

auth/src/main/java/com/firebase/ui/auth/provider/FacebookProvider.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@
2424
import com.facebook.FacebookCallback;
2525
import com.facebook.FacebookException;
2626
import com.facebook.FacebookSdk;
27+
import com.facebook.GraphRequest;
28+
import com.facebook.GraphResponse;
2729
import com.facebook.login.LoginManager;
2830
import com.facebook.login.LoginResult;
2931
import com.firebase.ui.auth.BuildConfig;
3032
import com.firebase.ui.auth.R;
3133
import com.google.firebase.auth.AuthCredential;
3234
import com.google.firebase.auth.FacebookAuthProvider;
3335

36+
import org.json.JSONException;
37+
import org.json.JSONObject;
38+
3439
import java.util.Arrays;
3540

3641
public class FacebookProvider implements IDPProvider, FacebookCallback<LoginResult> {
@@ -88,20 +93,37 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
8893
}
8994

9095
@Override
91-
public void onSuccess(LoginResult loginResult) {
96+
public void onSuccess(final LoginResult loginResult) {
9297
if (BuildConfig.DEBUG) {
9398
Log.d(TAG, "Login to facebook successful with Application Id: "
9499
+ loginResult.getAccessToken().getApplicationId()
95100
+ " with Token: "
96101
+ loginResult.getAccessToken().getToken());
97102
}
98-
mCallbackObject.onSuccess(createIDPResponse(loginResult));
103+
GraphRequest request = GraphRequest.newMeRequest(
104+
loginResult.getAccessToken(),
105+
new GraphRequest.GraphJSONObjectCallback() {
106+
@Override
107+
public void onCompleted(JSONObject object, GraphResponse response) {
108+
try {
109+
String email = object.getString("email");
110+
mCallbackObject.onSuccess(createIDPResponse(loginResult, email));
111+
} catch (JSONException e) {
112+
e.printStackTrace();
113+
mCallbackObject.onFailure(new Bundle());
114+
}
115+
}
116+
});
117+
Bundle parameters = new Bundle();
118+
parameters.putString("fields", "id,name,email");
119+
request.setParameters(parameters);
120+
request.executeAsync();
99121
}
100122

101-
private IDPResponse createIDPResponse(LoginResult loginResult) {
123+
private IDPResponse createIDPResponse(LoginResult loginResult, String email) {
102124
Bundle response = new Bundle();
103125
response.putString(ACCESS_TOKEN, loginResult.getAccessToken().getToken());
104-
return new IDPResponse(FacebookAuthProvider.PROVIDER_ID, response);
126+
return new IDPResponse(FacebookAuthProvider.PROVIDER_ID, email, response);
105127
}
106128

107129
public static AuthCredential createAuthCredential(IDPResponse response) {

auth/src/main/java/com/firebase/ui/auth/provider/GoogleProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public void setAuthenticationCallback(IDPCallback callback) {
8383
private IDPResponse createIDPResponse(GoogleSignInAccount account) {
8484
Bundle response = new Bundle();
8585
response.putString(TOKEN_KEY, account.getIdToken());
86-
return new IDPResponse(GoogleAuthProvider.PROVIDER_ID, response);
86+
return new IDPResponse(GoogleAuthProvider.PROVIDER_ID, account.getEmail(), response);
8787
}
8888

8989
@Override

auth/src/main/java/com/firebase/ui/auth/provider/IDPResponse.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@
2121
public class IDPResponse implements Parcelable {
2222

2323
private final String mProviderId;
24+
private final String mEmail;
2425
private final Bundle mResponseBundle;
2526

26-
public IDPResponse(String providerId, Bundle response) {
27+
public IDPResponse(String providerId, String email, Bundle response) {
2728
mProviderId = providerId;
29+
mEmail = email;
2830
mResponseBundle = response;
2931
}
3032

3133
public static final Creator<IDPResponse> CREATOR = new Creator<IDPResponse>() {
3234
@Override
3335
public IDPResponse createFromParcel(Parcel in) {
3436
return new IDPResponse(
37+
in.readString(),
3538
in.readString(),
3639
in.readBundle()
3740
);
@@ -51,6 +54,10 @@ public Bundle getResponse() {
5154
return mResponseBundle;
5255
}
5356

57+
public String getEmail() {
58+
return mEmail;
59+
}
60+
5461
@Override
5562
public int describeContents() {
5663
return 0;
@@ -59,6 +66,7 @@ public int describeContents() {
5966
@Override
6067
public void writeToParcel(Parcel dest, int flags) {
6168
dest.writeString(mProviderId);
69+
dest.writeString(mEmail);
6270
dest.writeBundle(mResponseBundle);
6371
}
6472
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ private void startEmailHandler(String email, List<String> providers) {
8686
mActivityHelper.getApplicationContext(),
8787
mActivityHelper.flowParams,
8888
provider,
89+
null,
8990
email);
9091
mActivityHelper.startActivityForResult(intent, RC_WELCOME_BACK_IDP);
9192
return;

auth/src/main/java/com/firebase/ui/auth/ui/account_link/AccountLinkInitActivity.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.support.annotation.NonNull;
2121

2222
import com.firebase.ui.auth.R;
23+
import com.firebase.ui.auth.provider.IDPResponse;
2324
import com.firebase.ui.auth.ui.ActivityHelper;
2425
import com.firebase.ui.auth.ui.AppCompatBase;
2526
import com.firebase.ui.auth.ui.ExtraConstants;
@@ -36,7 +37,7 @@
3637
import java.util.List;
3738

3839
public class AccountLinkInitActivity extends AppCompatBase {
39-
protected FirebaseAuthWrapper mApiWrapper;
40+
private IDPResponse mIdpResponse;
4041
private static final int RC_SAVE_CREDENTIALS = 3;
4142
private static final int RC_WELCOME_BACK_IDP_PROMPT = 4;
4243
private static final int RC_WELCOME_BACK_PASSWORD_PROMPT = 5;
@@ -45,6 +46,8 @@ public class AccountLinkInitActivity extends AppCompatBase {
4546
RC_WELCOME_BACK_IDP_PROMPT,
4647
RC_WELCOME_BACK_PASSWORD_PROMPT);
4748

49+
protected FirebaseAuthWrapper mApiWrapper;
50+
4851
@Override
4952
protected void onCreate(Bundle savedInstanceState) {
5053
super.onCreate(savedInstanceState);
@@ -54,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) {
5457
String email = getIntent().getStringExtra(ExtraConstants.EXTRA_EMAIL);
5558
String password = getIntent().getStringExtra(ExtraConstants.EXTRA_PASSWORD);
5659
String provider = getIntent().getStringExtra(ExtraConstants.EXTRA_PROVIDER);
60+
mIdpResponse = getIntent().getParcelableExtra(ExtraConstants.EXTRA_IDP_RESPONSE);
5761
next(email, password, provider);
5862
}
5963

@@ -81,7 +85,7 @@ public void onComplete(@NonNull Task<ProviderQueryResult> task) {
8185
// new account for this email
8286
startActivityForResult(SaveCredentialsActivity.createIntent(
8387
getApplicationContext(),
84-
null,
88+
mActivityHelper.flowParams,
8589
email,
8690
password,
8791
provider,
@@ -92,7 +96,7 @@ public void onComplete(@NonNull Task<ProviderQueryResult> task) {
9296
// existing account but has this IDP linked
9397
startActivityForResult(SaveCredentialsActivity.createIntent(
9498
AccountLinkInitActivity.this,
95-
null,
99+
mActivityHelper.flowParams,
96100
email,
97101
password,
98102
provider,
@@ -112,6 +116,7 @@ public void onComplete(@NonNull Task<ProviderQueryResult> task) {
112116
getApplicationContext(),
113117
mActivityHelper.flowParams,
114118
provider,
119+
mIdpResponse,
115120
email),
116121
RC_WELCOME_BACK_IDP_PROMPT
117122
);
@@ -123,6 +128,7 @@ public void onComplete(@NonNull Task<ProviderQueryResult> task) {
123128
getApplicationContext(),
124129
mActivityHelper.flowParams,
125130
provider,
131+
mIdpResponse,
126132
email),
127133
RC_WELCOME_BACK_IDP_PROMPT);
128134
}
@@ -135,10 +141,12 @@ public static Intent createIntent(
135141
FlowParameters flowParams,
136142
String email,
137143
String password,
144+
IDPResponse idpResponse,
138145
String provider) {
139146
return ActivityHelper.createBaseIntent(context, AccountLinkInitActivity.class, flowParams)
140147
.putExtra(ExtraConstants.EXTRA_EMAIL, email)
141148
.putExtra(ExtraConstants.EXTRA_PASSWORD, password)
149+
.putExtra(ExtraConstants.EXTRA_IDP_RESPONSE, idpResponse)
142150
.putExtra(ExtraConstants.EXTRA_PROVIDER, provider);
143151
}
144152
}

auth/src/main/java/com/firebase/ui/auth/ui/account_link/WelcomeBackIDPPrompt.java

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,40 @@ public class WelcomeBackIDPPrompt extends AppCompatBase
4747
implements View.OnClickListener, IDPProvider.IDPCallback {
4848

4949
private static final String TAG = "WelcomeBackIDPPrompt";
50-
51-
private IDPProvider mIDPProvider;
50+
private IDPProvider mIdpProvider;
5251
private String mProviderId;
53-
private IDPResponse mIdpResponse;
52+
private IDPResponse mPrevIdpResponse;
53+
private AuthCredential mPrevCredential;
54+
55+
private static AuthCredential getAuthCredential(IDPResponse idpResponse) {
56+
switch (idpResponse.getProviderType()) {
57+
case GoogleAuthProvider.PROVIDER_ID:
58+
return GoogleProvider.createAuthCredential(idpResponse);
59+
case FacebookAuthProvider.PROVIDER_ID:
60+
return FacebookProvider.createAuthCredential(idpResponse);
61+
default:
62+
return null;
63+
}
64+
}
65+
5466

5567
@Override
5668
protected void onCreate(Bundle savedInstanceState) {
5769
super.onCreate(savedInstanceState);
5870
setTitle(getResources().getString(R.string.sign_in));
5971
mProviderId = getProviderIdFromIntent();
60-
mIdpResponse = getIntent().getParcelableExtra(ExtraConstants.EXTRA_IDP_RESPONSE);
72+
mPrevIdpResponse = getIntent().getParcelableExtra(ExtraConstants.EXTRA_IDP_RESPONSE);
6173
setContentView(R.layout.welcome_back_idp_prompt_layout);
6274

63-
mIDPProvider = null;
75+
mIdpProvider = null;
6476
for (IDPProviderParcel providerParcel: mActivityHelper.flowParams.providerInfo) {
6577
if (mProviderId.equals(providerParcel.getProviderType())) {
6678
switch (mProviderId) {
6779
case GoogleAuthProvider.PROVIDER_ID:
68-
mIDPProvider = new GoogleProvider(this, providerParcel);
80+
mIdpProvider = new GoogleProvider(this, providerParcel);
6981
break;
7082
case FacebookAuthProvider.PROVIDER_ID:
71-
mIDPProvider = new FacebookProvider(this, providerParcel);
83+
mIdpProvider = new FacebookProvider(this, providerParcel);
7284
break;
7385
default:
7486
Log.w(TAG, "Unknown provider: " + mProviderId);
@@ -78,7 +90,11 @@ protected void onCreate(Bundle savedInstanceState) {
7890
}
7991
}
8092

81-
if (mIDPProvider == null) {
93+
if (mPrevIdpResponse != null) {
94+
mPrevCredential = getAuthCredential(mPrevIdpResponse);
95+
}
96+
97+
if (mIdpProvider == null) {
8298
getIntent().putExtra(
8399
ExtraConstants.EXTRA_ERROR_MESSAGE,
84100
"Firebase login successful. Account linking failed due to provider not "
@@ -87,48 +103,42 @@ protected void onCreate(Bundle savedInstanceState) {
87103
}
88104

89105
((TextView) findViewById(R.id.welcome_back_idp_prompt))
90-
.setText(getIdpPromptString(getEmailFromIntent(), getAppNameFromIntent()));
106+
.setText(getIdpPromptString(getEmailFromIntent()));
91107

92-
mIDPProvider.setAuthenticationCallback(this);
108+
mIdpProvider.setAuthenticationCallback(this);
93109
findViewById(R.id.welcome_back_idp_button).setOnClickListener(new View.OnClickListener() {
94110
@Override
95111
public void onClick(View view) {
96-
mIDPProvider.startLogin(WelcomeBackIDPPrompt.this, getEmailFromIntent());
112+
mIdpProvider.startLogin(WelcomeBackIDPPrompt.this, getEmailFromIntent());
97113
}
98114
});
99115
}
100116

101-
private String getIdpPromptString(String email, String appName) {
117+
private String getIdpPromptString(String email) {
102118
String promptStringTemplate = getResources().getString(R.string.welcome_back_idp_prompt);
103-
return String.format(promptStringTemplate, email, appName, mIDPProvider.getName(this));
119+
return String.format(promptStringTemplate, email, mIdpProvider.getName(this));
104120
}
105121

106122
@Override
107123
public void onActivityResult(int requestCode, int resultCode, Intent data) {
108124
super.onActivityResult(requestCode, resultCode, data);
109-
mIDPProvider.onActivityResult(requestCode, resultCode, data);
125+
mIdpProvider.onActivityResult(requestCode, resultCode, data);
110126
}
111127

112128
@Override
113129
public void onClick(View view) {
114-
next(mIdpResponse, mProviderId);
130+
next(mPrevIdpResponse);
115131
}
116132

117133
@Override
118134
public void onSuccess(IDPResponse idpResponse) {
119-
Intent data = getIntent();
120-
data.putExtra(ExtraConstants.EXTRA_PROVIDER, mProviderId);
121-
next(idpResponse, mProviderId);
135+
next(idpResponse);
122136
}
123137

124138
@Override
125139
public void onFailure(Bundle extra) {
126140
Toast.makeText(getApplicationContext(), "Error signing in", Toast.LENGTH_LONG).show();
127-
next(mIdpResponse, mProviderId);
128-
}
129-
130-
private String getAppNameFromIntent() {
131-
return getIntent().getStringExtra(ExtraConstants.EXTRA_EMAIL);
141+
finish(RESULT_CANCELED, new Intent());
132142
}
133143

134144
private String getProviderIdFromIntent() {
@@ -139,43 +149,47 @@ private String getEmailFromIntent() {
139149
return getIntent().getStringExtra(ExtraConstants.EXTRA_EMAIL);
140150
}
141151

142-
private void next(IDPResponse idpResponse, String provider) {
143-
if (idpResponse == null) {
152+
private void next(IDPResponse newIdpResponse) {
153+
if (newIdpResponse == null) {
144154
return; // do nothing
145155
}
146-
AuthCredential credential;
147-
switch (provider) {
148-
case GoogleAuthProvider.PROVIDER_ID:
149-
credential = GoogleProvider.createAuthCredential(idpResponse);
150-
break;
151-
case FacebookAuthProvider.PROVIDER_ID:
152-
credential = FacebookProvider.createAuthCredential(idpResponse);
153-
break;
154-
default:
155-
Log.e(TAG, "Unknown provider: " + provider);
156-
finish(Activity.RESULT_FIRST_USER, new Intent());
157-
return;
158-
}
159-
if (credential == null) {
156+
AuthCredential newCredential;
157+
newCredential = getAuthCredential(newIdpResponse);
158+
if (newCredential == null) {
160159
Log.e(TAG, "No credential returned");
161160
finish(Activity.RESULT_FIRST_USER, new Intent());
162161
return;
163162
}
164163

165-
FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
164+
final FirebaseAuth firebaseAuth = mActivityHelper.getFirebaseAuth();
166165
FirebaseUser currentUser = firebaseAuth.getCurrentUser();
167166

168167
if (currentUser == null) {
169-
Task<AuthResult> authResultTask = firebaseAuth.signInWithCredential(credential);
168+
Task<AuthResult> authResultTask = firebaseAuth.signInWithCredential(newCredential);
170169
authResultTask.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
171170
@Override
172171
public void onComplete(@NonNull Task<AuthResult> task) {
173-
finish(Activity.RESULT_OK, new Intent());
172+
if (task.isSuccessful() && mPrevCredential != null) {
173+
FirebaseUser firebaseUser = task.getResult().getUser();
174+
firebaseUser.linkWithCredential(mPrevCredential);
175+
firebaseAuth.signOut();
176+
firebaseAuth.signInWithCredential(mPrevCredential).addOnCompleteListener(
177+
new OnCompleteListener<AuthResult>() {
178+
@Override
179+
public void onComplete(@NonNull Task<AuthResult> task) {
180+
finish(Activity.RESULT_OK, new Intent());
181+
182+
}
183+
}
184+
);
185+
} else {
186+
finish(Activity.RESULT_OK, new Intent());
187+
}
174188
}
175189
});
176190

177191
} else {
178-
Task<AuthResult> authResultTask = currentUser.linkWithCredential(credential);
192+
Task<AuthResult> authResultTask = currentUser.linkWithCredential(newCredential);
179193
authResultTask.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
180194
@Override
181195
public void onComplete(@NonNull Task<AuthResult> task) {
@@ -189,9 +203,11 @@ public static Intent createIntent(
189203
Context context,
190204
FlowParameters flowParams,
191205
String providerId,
206+
IDPResponse idpResponse,
192207
String email) {
193208
return ActivityHelper.createBaseIntent(context, WelcomeBackIDPPrompt.class, flowParams)
194209
.putExtra(ExtraConstants.EXTRA_PROVIDER, providerId)
210+
.putExtra(ExtraConstants.EXTRA_IDP_RESPONSE, idpResponse)
195211
.putExtra(ExtraConstants.EXTRA_EMAIL, email);
196212
}
197213
}

0 commit comments

Comments
 (0)