Flutter - How to link social account using Firebase facebook and google plugin - flutter

I have a flutter app and would like the user to authenticate both with FB and Google. I do not want multiple accounts, just a single account that links both.
I am using :
firebase_auth 0.15.1
google_sign_in 4.0.14
facebook_plugin 3.0.0
I am not able to get the email address of the user when the user's account already exist with a different provider. The email is needed in order to get the list of providers for that user using the API call "fetchSignInMethodsForEmail"
Here is an example:
1: User login with Google credentials. The account is created in firebase and google is linked.
2: The user now logoff
3: The user now tries to login with FB with the same email.
-- User get the following error
code:"ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL"
details: null
message: "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address., **null**))
As you can see the email is null. I need the email in order to get a list of providers. Then I can redirect the user to correct provider
here is a snippet of my code
Future<FirebaseUser> signInWithFacebook({bool isIos}) async {
AuthCredential credential;
try {
final FacebookLoginResult result = await facebookLogin.logIn(['email']);
if (result.accessToken != null) {
credential = FacebookAuthProvider.getCredential(
accessToken: result.accessToken.token
);
AuthResult authResult = await _firebaseAuth.signInWithCredential(
credential,
);
firebaseUser = authResult.user;
return firebaseUser;
} catch (e) {
throw Exception(e);
}
return null;
}
Thanks for your help

Related

AWS Amplify Flutter - Migrating user id from guest user to authenticated user

I'm using AWS Amplify with Cognito for authenticating users in my Flutter Application.
Users can use the app without having to sign up immediately, by using Cognito's Guest Authentication feature. A user can optionally sign up later on using the Amplify.Auth.signUp method.
The problem is that after signing up and then logging in, the created user has another ID than the guest user. Is there a way to keep the old ID across signup? If not, what options do I have besides updating all of the user's database items to the new ID?
I've seen that the js version of amplify supports this behavior by default.
I'm using this code to get the user's ID:
Future<String> getUserId() async {
final currentUser = await Amplify.Auth.fetchAuthSession(options: const CognitoSessionOptions(getAWSCredentials: true)) as CognitoAuthSession;
final uid = currentUser.identityId?.split(':').last;
if (uid == null) {
throw RemoteException(S.current.error_no_user_logged_in);
}
return uid;
}

Firebase Auth Error No Corresponding User Record but user exist (Flutter)

I've been logging in fine on my app using Firebase sign in with email/password auth but now it keeps returning the error :
There is no user record corresponding to this identifier. The user may have been deleted.
The user email address and account exist so I can't really tell why I get that error.
Here's my code to sign in:
final user = await signInWithEmail(context,'${driverIDController!.text}', passwordController!.text,);
And the email util function
final signInFunc = () => FirebaseAuth.instance.signInWithEmailAndPassword(email: email.trim(), password: password); return signInOrCreateAccount(context, signInFunc);
Any thoughts or suggestions on this problem?

my flutter app doesn't open authentication link

I am using firebase authentication and facebook authentication to facilitate users auth.
But when I click the button for face book auth it stops loading and nothing happens.
and in the release mode the link doesn't open.
I have tried all youtube videos to make facebook auth work.
This is my source code:
Future<UserCredential> signInWithFacebook() async {
// Trigger the sign-in flow
final LoginResult loginResult = await FacebookAuth.instance.login();
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken!.token);
// Once signed in, return the UserCredential
return _auth.signInWithCredential(facebookAuthCredential);
}
Facebook have already updated their api for signin options.
try reading this links it might help
ff:
[https://pub.dev/packages/flutter_facebook_auth]
[https://medium.com/flutter-community/flutter-facebook-login-77fcd187242]
![and also for the fb api i have use a webview to fetch it and send the request to the post]

Link Firebase user with another provider

I would like to force users that previously authenticated with Facebook to sign up using a new provider. The reason for this is that I would like to remove Facebook as an authentication provider. I would unlink the user once the user has been successfully linked with the new provider.
For example, the user is presented with new authentication options and the user selects to continue with email. I have the following code:
func createUserAndSignIn(
username: String,
email: String,
password: String
) async throws -> String {
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
// if user is already logged in (in this case with Facebook)
if let user = Auth.auth().currentUser {
try await user.link(with: credential)
}
do {
let authDataResult = try await Auth.auth().createUser(withEmail: email, password: password)
return authDataResult.user.uid
} catch {
// throw error
}
}
The linking of accounts (user.link(with:)) fails with the following error:
Domain=FIRAuthErrorDomain Code=17014 "This operation is sensitive and requires recent authentication. Log in again before retrying this request." UserInfo={NSLocalizedDescription=This operation is sensitive and requires recent authentication. Log in again before retrying this request., FIRAuthErrorUserInfoNameKey=ERROR_REQUIRES_RECENT_LOGIN}
Would this be even be the correct approach for this?
You have to re-authenticate the user. Using the current credential
if
let user = Auth.auth().currentUser,
let currentAccessToken = AccessToken.current
{
// Prompt the user to re-provide their sign-in credentials
let result = try await user.reauthenticate(
with: FacebookAuthProvider.credential(withAccessToken: currentAccessToken.tokenString)
)
// Then link the user
try await user.link(with: newCredential)
// User can be unlinked from Facebook
try await Auth.auth().currentUser?.unlink(fromProvider: "facebook.com")
}
This is needed for several operations such as updating the user's email, password or deleting the user.
The approach you're taking is close. The error you're getting is because some operations in firebase require a recent authentication to have taken place:
FIRAuthErrorCodeRequiresRecentLogin: Updating a user’s email is a
security sensitive operation that requires a recent login from the
user. This error indicates the user has not signed in recently enough.
To resolve, reauthenticate the user by invoking
reauthenticateWithCredential:completion: on FIRUser. [1]
The steps you want to take are:
Authenticate the user with an existing auth method.
Prompt the user for their email and password
Use the email and password to create an AuthCredential object.
Pass that AuthCredential object to the user's linkWithCredential method.
There's a complete walkthrough for this in the Firebase docs: https://firebase.google.com/docs/auth/web/account-linking#link-email-address-and-password-credentials-to-a-user-account
But the key point is that you have to authenticate the user with an existing provider before you do this, even if they are technically "logged in".
Note that the steps are slightly different if you want to link the user to another Auth provider other than email (such as Google): https://firebase.google.com/docs/auth/web/account-linking#link-federated-auth-provider-credentials-to-a-user-account
After that, if you wish, you can use unlink to remove the Facebook authentication.

How to sign a Azure AD user into Firebase in a Flutter mobile app?

For a Flutter mobile app I am trying to use a Microsoft OAuthProvider to get a Firebase credential with which to sign the user into Firebase with their Azure AD account.
The closest I got was using a third party Active Directory auth package to log the user in and get an access token. However the sign-in to Firebase fails with an error message that suggests the idToken is invalid.
final AadOAuth oauth = new AadOAuth(config);
await oauth.login();
// accessToken looks legit
String accessToken = await oauth.getAccessToken();
String idToken = await oauth.getIdToken();
OAuthProvider provider = OAuthProvider('microsoft.com');
// Also tried the constructor without the idToken
OAuthCredential credential = provider.credential(accessToken: accessToken, idToken: idToken);
// app fails here:
await FirebaseAuth.instance.signInWithCredential(credential);
// this works fine, but only on web platform:
await FirebaseAuth.instance.signInWithPopup(provider);
Because it is a platform specific error (iOS in this case), the exception details are not surfaced. All I get is:
PlatformException(internal-error, ) nativeErrorCode: 17999
Here is my app settings in the Azure portal:
Full manifest here
Has anyone been successful in using Microsoft Auth to sign a user in to Firebase in a Flutter mobile app?
You can use Firebase Auth OAuth package for it.
And sign in to the firebase using the Microsoft Auth provider.
User user = await FirebaseAuthOAuth().openSignInFlow(
"microsoft.com", ["email openid"], {'tenant': 'your-tenent-id'});
This integrates nicely with firebase so, firebase authStateChange also works with this method.
You have just to not receiving idToken, just verify that you have add the id_token for the response_type and also openid scope like
provider.addScope('openid');
Also check weather you have allowed implicit flow with id token in the Azure portal app settings (you sould check ID tokens on the Authentication tab under Implicit grant section).
Ok than have you added Microsoft as a authentication provider in the firebase authentication configuration Sign-in method page? And also have you tried to authenticate with Auth, after getCredentials method as stated in the documentation?
provider.getCredentialWith(nil) { credential, error in
if error != nil {
// Handle error.
}
if credential != nil {
Auth().signIn(with: credential) { authResult, error in
if error != nil {
// Handle error.
}
// User is signed in.
// IdP data available in authResult.additionalUserInfo.profile.
// OAuth access token can also be retrieved:
// authResult.credential.accessToken
// OAuth ID token can also be retrieved:
// authResult.credential.idToken
}
}
}
firebase authentication package has a method called signInWithPopup so you don't need firebase_auth_oauth anymore. here my code:
Future<UserCredential?> loginWithMicrosoft() async {
OAuthProvider provider = OAuthProvider('microsoft.com');
provider.setCustomParameters({
"tenant": "your-tenant-id",
});
provider.addScope('user.read');
provider.addScope('profile');
try {
final userCredential = await FirebaseAuth.instance.signInWithPopup(provider);
return userCredential;
} on FirebaseAuthException catch(err) {
debugPrint(err.message);
// Handle FirebaseAuthExceptions
// ex: firebase_auth/account-exists-with-different-credential
}
}
Remeber add the redirect URI and enable de scopes in Azure Portal.