in my mobile app i have 4 methods of login:
- Normal sign in/log in using e-mail and password
- Google Sign In
- Flutter Facebook Auth
- Sign In With Apple
The problem is for example when I create my account using Google Sign In with [email protected], then i log out and try to login using my Facebook account which is created with the same e-mail there's error. Summing up every single login function works independently.
I wonder if it's possible to handle this with cloud function?
Here's Flutter code:
///GOOGLE
static Future<bool> signWithGoogle() async {
// return false;
final GoogleSignIn _googleSignIn = GoogleSignIn( scopes: ['email'] );
GoogleSignInAccount? account = await _googleSignIn.signIn();
googleSignInAccount = account;
if (account == null) return false;
GoogleSignInAuthentication authentication = await account.authentication;
String? email = _googleSignIn.currentUser!.email;
final bool firstLogin = await isFirstLogin(email);
ParseResponse response;
if (firstLogin){
response = await ParseUser.loginWith(
'google',
google(
authentication.accessToken!,
_googleSignIn.currentUser!.id,
authentication.idToken!
),
username: _googleSignIn.currentUser!.displayName,
email: email,
);
}else {
response = await ParseUser.loginWith(
'google',
google(
authentication.accessToken!,
_googleSignIn.currentUser!.id,
authentication.idToken!
),
);
}
if (response.success){
return _setDeviceId(response.result);
}else
_handleError(response);
return false;
}
static Future<GoogleSignInAccount?> googleForDataOnly() async {
final GoogleSignIn _googleSignIn = GoogleSignIn( scopes: ['email'] );
return await _googleSignIn.signIn();
}
///FACEBOOK
static Future<bool> signWithFacebook() async {
final LoginResult result = await FacebookAuth.instance.login(permissions: [
'email',
'public_profile',
'user_location'
]);
if (result.status == LoginStatus.cancelled) return false;
if (result.status == LoginStatus.success) {
if (result.accessToken == null) {
Fluttertoast.showToast(msg: Translate.unknownError());
return false;
}
final userData = await FacebookAuth.instance.getUserData();
String? email = userData['email'];
if (email == null || email.isEmpty){
Fluttertoast.showToast(msg: Translate.emailPermissionRequired());
return false;
}
final bool firstLogin = await isFirstLogin(email);
ParseResponse response;
if (firstLogin){
response = await ParseUser.loginWith(
'facebook',
facebook(result.accessToken!.token,
result.accessToken!.userId,
result.accessToken!.expires
),
email: email,
username: userData['name']
);
}else {
response = await ParseUser.loginWith(
'facebook',
facebook(result.accessToken!.token,
result.accessToken!.userId,
result.accessToken!.expires
),
);
}
if (response.success) return _setDeviceId(response.result);
else _handleError(response);
}
return false;
}
static Future<bool> facebookDataOnly() async {
final LoginResult result = await FacebookAuth.instance.login(permissions: [
'email',
'public_profile',
'user_location'
]);
if (result.status == LoginStatus.cancelled) return false;
if (result.status == LoginStatus.success) {
if (result.accessToken == null) {
Fluttertoast.showToast(msg: Translate.unknownError());
return false;
}
return true;
}
return false;
}
///APPLE
static Future<bool> signWithApple() async {
final AuthorizationCredentialAppleID credential = await SignInWithApple.getAppleIDCredential(
scopes: [AppleIDAuthorizationScopes.email, AppleIDAuthorizationScopes.fullName],
);
final String? email = credential.email;
final String? name = credential.givenName;
final String? famName = credential.familyName;
String? userName;
if (name != null && famName != null){
userName = '$name $famName';
}
if (email == null) {
Fluttertoast.showToast(msg: Translate.invalidEmail());
return false;
}
final bool firstLogin = await isFirstLogin(email);
print(firstLogin);
ParseResponse response;
if (firstLogin){
response = await ParseUser.loginWith(
'apple',
apple(
credential.identityToken!,
credential.userIdentifier!
),
email: email,
username: userName
);
}else {
response = await ParseUser.loginWith(
'apple',
apple(
credential.identityToken!,
credential.userIdentifier!
),
);
}
if (response.success){
return _setDeviceId(response.result);
}else {
_handleError(response);
}
_sendLoginInfo(credential, response.success);
return false;
}
What you're missing is a functionality called linking users, I didn't find built-in function in Flutter SDK so I'm attaching docs from REST API.
You're supposed to populate
authDataattribute of user with login provider data in order to link it to the user. This can be done with a help of a cloud code or a simple http request from client. Let's say that you will integrate this in your flutter app the request for linking facebook login provider should be made of: