1
votes

I am using code directly from facebook docs: https://developers.facebook.com/docs/javascript/quickstart/

<body>
    <script>
        //this gets called immediately after sdk.js loads 
        window.fbAsyncInit = function() {

            FB.init({
                appId            : '12345...MYIDHERE...6789',
                autoLogAppEvents : true,
                xfbml            : true,
                version          : 'v5.0'
            });

            //check if user is logged in...
            FB.getLoginStatus(function (response) {   
                    console.log('initial-check:', response);
            });
        };

        //check if user is logged in... - AFTER facebook Login Popup returns.
        function callback_afterLogin() {
            FB.getLoginStatus(function (response) {   
                console.log('callback_afterLogin:', response);
            });
        }
    </script>
    <script async defer src="https://connect.facebook.net/en_US/sdk.js"></script>

    <div class="fb-login-button" 
        data-size="large"
        data-button-type="login_with" 
        data-auto-logout-link="true"
        onlogin="callback_afterLogin"
        data-use-continue-as="false">
    </div>

</body>

The fb-login-button renders as 'Log Out', which indicates to me the button detects I am already logged into Facebook AND also into the App itself.

The problem is the FB.getLoginStatus() response.status === 'unknown' ! Why ? I would have expected it to show 'connected'. The button clearly knows I am connected, why then the status contradicts this.

enter image description here

Furthermore, I then logout, and the button changes to 'Log in with Facebook'; then I attempt to log back in, which shows the Facebook Popup window; Upon entering the correct email/password combo, and clicking Login, I end back at my App's page, BUT the onlogin callback function (onlogin="callback_afterLogin") FIRES TWICE ! The first time, it shows the correct [status: "connected"] but the second time it shows [status: "unknown"], giving the appearance that I am logged out. There should be no reason for it to fire twice ?!

enter image description here

Furthermore, there is a .toLowerCase() error originating from the facebook sdk.js (see second screenshot).

2

2 Answers

2
votes

You will still be able to use HTTP with “localhost” addresses, but only while your app is still in development mode.

The above quote comes from facebook staff from a blog post at https://developers.facebook.com/blog/post/2018/06/08/enforce-https-facebook-login/

I was relying on it to be truthful, but apparently IT SHOULD NOT BE TRUSTED and is the cause of the weird behaviour documented in my question.

As soon as I started using HTTPS ( https://localhost ), the sdk library behaves better:

  • initial status is now "connected"
  • callback still fires twice, but both times status is "connected"

A new error message appears in-between the firing twice callbacks:

You are overriding current access token, that means some other app is expecting different access token and you will probably break things. Please consider passing access_token directly to API parameters instead of overriding the global settings.

I tweaked the code slightly, thinking this would fix the firing twice problem:

//check if user is logged in... - AFTER facebook Login Popup returns.
function callback_afterLogin(response) {
    //REMOVED FB.getLoginStatus call, added `response` parm to callback signature
    console.log('callback_afterLogin:', response );
}

BUT it did not make a difference, still fires twice in succession, with error message in between. Please post your solution if you know why it fires twice.

ALSO NOTE the .toLowerCase() error remains, under certain conditions.

0
votes

I was struggling with .toLowerCase() when logging out, maybe my demo helps. Atleast for me it works now. facebook api references

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Facebook</title>
</head>

<body>
  <script>
    window.fbAsyncInit = function () {
      FB.init({
        appId: 'your-id',
        cookie: true,
        xfbml: true,
        version: 'v5.0'
      });

      FB.getLoginStatus(function (response) {
        statusChangeCallback(response);
      })
    };

    (function (d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) { return; }
      js = d.createElement(s); js.id = id;
      js.src = "https://connect.facebook.net/en_US/sdk.js";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));

    function statusChangeCallback(response) {
      if (response.status === "connected") {
        console.log("Logged in and authenticated.")
        testAPI();
      } else {
        console.log("not authenticated")
      }
    }
    function logout() {
      FB.logout(function (response) {
        let profile = ""
        document.getElementById("profile").innerHTML = profile;
      });
    }
    function testAPI() {
      FB.api('/me?fields=id,name', function (response) {
        if (response && !response.error)
          buildProfile(response)
      })
    }
    function login() {
      FB.login(function (response) {
        if (response.authResponse) {
          console.log('Welcome!  Fetching your information.... ');
          FB.api('/me', function (response) {
            buildProfile(response)
            console.log('Good to see you, ' + response.name + '.');
          });
        } else {
          console.log('User cancelled login or did not fully authorize.');
        }
      });
    }
    function buildProfile(user) {
      let profile = `
        <h3>${user.name}</h3>
        <p>${user.email}</p>
        <p>${user.id}</p>
      `;
      document.getElementById('profile').innerHTML = profile;
    }
  </script>
  <a href="#" onclick="logout()">Logout</a>
  <a href="#" onclick="login()">Login</a>
  <div id="profile"></div>
</body>

</html>