Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FB login callback function not responding if user is already logged in facebook

I am using fb connect using js. This is my code:

<script>
    window.fbAsyncInit = function() {
      FB.init({
        appId      : 'xxxxxxxxxxxxxxxx',
        status     : true, 
        cookie     : true,
        xfbml      : true,
        oauth      : true
      });

      FB.Event.subscribe('auth.login', function(response) {
        obj=response.authResponse;
        token=obj.accessToken;
        setCookie("access_token_fb", token, '2');

        window.location.reload();
      },true);
    };
    (function(d){
       var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
       js = d.createElement('script'); js.id = id; js.async = true;
       js.src = "//connect.facebook.net/en_US/all.js";
       d.getElementsByTagName('head')[0].appendChild(js);
     }(document));
  </script>

for login I am using:

 <div class="fb-login-button" scope="email,user_checkins"  >Login with Facebook</div>

'auth.login' in subscribe function has a response handler it is only being called when user click on fb button and not already logged into FB, enter his/her email address and password in fb window . While if a user is already logged in facebook then fb dialog open and close. It doesnot then pass control to response hander. I read somewhere that force="true" enable it to detect status change and call call back function. But I don't know where to add force ture. I think it should be in login div. Is it true or is there some other approach?

thanks for you time.

like image 386
Hafiz Avatar asked Dec 16 '11 22:12

Hafiz


3 Answers

Method 1:

Though I believe that DMCS has given a correct solution to the problem, here is another way to approach. Use FB.login method with a custom login link.

<script>
window.fbAsyncInit = function() {
    FB.init({
        appId: 'YOUR-APP-ID',
        status: true,
        cookie: true,
        xfbml: true,
        oauth: true
    });
};

function facebookLogin() {
    FB.login(function(response) {
        if (response.authResponse) {
            console.log('Authenticated!');
            // location.reload(); //or do whatever you want
        } else {
            console.log('User cancelled login or did not fully authorize.');
        }
    },
    {
        scope: 'email,user_checkins'
    });
}

(function(d) {
    var js,
    id = 'facebook-jssdk';
    if (d.getElementById(id)) {
        return;
    }
    js = d.createElement('script');
    js.id = id;
    js.async = true;
    js.src = "//connect.facebook.net/en_US/all.js";
    d.getElementsByTagName('head')[0].appendChild(js);
} (document));
</script>

Body markup:

<div id='fb-root></div><!-- required for SDK initialization -->
<a id='fb-login' href='#' onclick='facebookLogin()'>Login with Facebook</a>

When you click on the button, it will run the callback function inside FB.login.

Method 2:

Alternatively, using FB login button plugin, you can subscribe to auth.statusChange and check for the status of the user in response.

FB.Event.subscribe('auth.statusChange', function(response) {
  // check for status in the response
});

Note if you are using fb login button plugin, and the user is already logged in and connected to the app, no login button is shown (read it in the documentation here)

like image 196
Jai Pandya Avatar answered Nov 09 '22 13:11

Jai Pandya


I'd suggest letting Facebook do the heavy lifting for you. Please note some changes: 1. channelUrl specified, 2. use of FB.getLoginStatus 3. removal of setting a cookie. 4. change of event to listen to (so in case they log out in a different window, or deauth your app elsewhere, etc )

    <script>
        window.fbAsyncInit = function() {
        FB.init({
            appId      : 'xxxxxxxxxxxxxxxx',
            status     : true, 
            cookie     : true,
            xfbml      : true,
            oauth      : true,
            channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html' // Channel File
        });

        FB.getLoginStatus(function(response) {
            if (response.status === 'connected') {

                var uid = response.authResponse.userID;
                var accessToken = response.authResponse.accessToken;

                // Do something with the access token


            } else {
                // Subscribe to the event 'auth.authResponseChange' and wait for the user to autenticate
                FB.Event.subscribe('auth.authResponseChange', function(response) {
                    // nothing more needed than to reload the page
                    window.location.reload();
                },true);      

                // now dynamically show the login plugin
                $('#mydiv').show();      
            }
        });


        };
        (function(d){
            var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
            js = d.createElement('script'); js.id = id; js.async = true;
            js.src = "//connect.facebook.net/en_US/all.js";
            d.getElementsByTagName('head')[0].appendChild(js);
        }(document));
  </script>
like image 6
DMCS Avatar answered Nov 09 '22 11:11

DMCS


When you intialize the FB SDK with status:true it will fetch the login status from the user and store it. From that point on when you make calls to FB.getLoginStatus() it isnt accessing fetching the latest data from FB but is instead referring to the locally stored variables that were set at the point of FB.init() - I think its only refreshed once every 20 mins (see https://github.com/facebook/facebook-js-sdk/commit/5b15174c7c9b9ea669499804d4a4c7d80771b036) - however you can force the refresh by doing this:

FB.getLoginStatus(function() {...}, /*FORCE*/ true);

This should then fire your auth.login event or you could just pass the handler you defined for that event to FB.getLoginStatus as well.

Can even go a set further and poll this function like:

setTimeout(function() {
    FB.getLoginStatus(function() {...}, /*FORCE*/ true);
}, 10000); // poll every 10 seconds
like image 2
nav Avatar answered Nov 09 '22 13:11

nav