Flutter - Firebase Authentication with facebook won't save the user information to the database

1,210

I almost forgot about this query. I finally solved how to get it work correctly, so I am posting the code below for anyone that wants to use it. Hope it helps!

  //Login with Facebook
  void signInUsingFacebook() async {
    final FacebookLogin facebookLogin = FacebookLogin();
    final FacebookLoginResult facebookLoginResult =
        await facebookLogin.logIn(['email']);
    switch (facebookLoginResult.status) {
      case FacebookLoginStatus.loggedIn:
        setState(() {
          showSpinner = true;
        });
        // TODO: Handle this case.
        FirebaseAuth.instance
            .signInWithCredential(
          FacebookAuthProvider.getCredential(
              accessToken: facebookLoginResult.accessToken.token),
        )
            .then((user) async {
          await _pushNotificationService.initialise();
          final graphResponse = await http.get(
              'https://graph.facebook.com/v2.12/me?fields=name,picture,email&access_token=${facebookLoginResult.accessToken.token}');
          final profile = JSON.jsonDecode(graphResponse.body);

          final DocumentSnapshot doc =
              await usersRef.document(user.user.uid).get();
          //Storing the user data in the firestore database

          if (!doc.exists) {
            final userDetails = await Navigator.push(
                context, MaterialPageRoute(builder: (ctx) => CreateAccount()));

            _db.collection("users").document(user.user.uid).setData({
              "username": userDetails[0],
              "displayName": userDetails[1],
              "email": profile['email'],
              "photUrl": "N/A",
              "gender": userDetails[2],
              "timestamp": timestamp,
              "signin_method": 'Facebook',
              "location": userDetails[4],
              "uid": user.user.uid,
              "points": 0,
              "bio": userDetails[3],
            });
          }
          setState(() {
            showSpinner = false;
          });
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => UserProfile(),
            ),
          );
        });

        break;
      case FacebookLoginStatus.cancelledByUser:
        // TODO: Handle this case.
        setState(() {
          showSpinner = false;
        });

        break;
      case FacebookLoginStatus.error:
        // TODO: Handle this case.
        setState(() {
          showSpinner = false;
        });

        break;
    }
  }

Explanation: The main difference between the code from the question and answer is this part:

// TODO: Handle this case.
        FirebaseAuth.instance
            .signInWithCredential(
          FacebookAuthProvider.getCredential(
              accessToken: facebookLoginResult.accessToken.token),
        ).then((user))async{}

Getting the current user object first and then trying to get the accesstoken for that current user doesn't work on the current version of flutter_facebook_login package. You have to use the FirebaseAuth.instance.signInWithCredential() method and use the FacebooAuthProvider().getCredential(accessToken:) This will let the firebase to sign in with the credentials and return the current user object. Now you can use the current user object to store details to the firestore database.

Note: Facebook returns the user details in JSON format. So you have to decode the JSON data before you can use it. The code to decode the JSON data is below:

final graphResponse = await http.get(
              'https://graph.facebook.com/v2.12/me?fields=name,picture,email&access_token=${facebookLoginResult.accessToken.token}');
          final profile = JSON.jsonDecode(graphResponse.body);

Hope it will help! CHEERS

Share:
1,210
hasib_ullah
Author by

hasib_ullah

Simplicity is prerequisite for reliability and I deliver both

Updated on December 19, 2022

Comments

  • hasib_ullah
    hasib_ullah over 1 year

    I want to let the user sign in with facebook and check if the user already exists in the database or not. If the user(uid) already exists then it should sign in normally but if the user is not in the database then I want to send the user to the create account page. This is my code but it's not working. This lets the user to sign in but is not fetching any data from the user profile, what can I do?

      //Login with Facebook
      void signInUsingFacebook() async {
        final FacebookLogin facebookLogin = FacebookLogin();
        final FacebookLoginResult facebookLoginResult =
            await facebookLogin.logIn(['email']);
        switch (facebookLoginResult.status) {
          case FacebookLoginStatus.loggedIn:
            // TODO: Handle this case.
            FirebaseAuth.instance.signInWithCredential(
              FacebookAuthProvider.getCredential(
                  accessToken: facebookLoginResult.accessToken.token),
            );
            FirebaseUser currentUser = await FirebaseAuth.instance.currentUser();
            if (currentUser != null) {
              print('user is logged in');
              await _pushNotificationService.initialise();
    
              final DocumentSnapshot doc =
                  await usersRef.document(currentUser.uid).get();
              //Storing the user data in the firestore database
    
              if (!doc.exists) {
                final userDetails = await Navigator.push(context,
                    MaterialPageRoute(builder: (context) => CreateAccount()));
                _db.collection("users").document(currentUser.uid).setData({
                  "username": userDetails[1],
                  "displayName": userDetails[2],
                  "email": currentUser.email,
                  "photUrl": userDetails[0],
                  "gender": userDetails[3],
                  "timestamp": timestamp,
                  "signin_method": currentUser.providerId,
                  "location": userDetails[4],
                  "uid": currentUser.uid,
                  "points": 0,
                  "bio": userDetails[5],
                });
              }
            }
            break;
          case FacebookLoginStatus.cancelledByUser:
            // TODO: Handle this case.
            print('cancelled by user');
            break;
          case FacebookLoginStatus.error:
            // TODO: Handle this case.
            print('login error');
            break;
        }
    
    
  • rizerphe
    rizerphe almost 4 years
    While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
  • hasib_ullah
    hasib_ullah almost 4 years
    Thank you for pointing that out. I will definitely add the explanation behind this code.