Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Facebook login JS - FB.Event.subscribe('auth.login') triggers without login button click

really need your help with log-in-with-facebook feature I'm trying to implement on my website.

Basically, I'm trying to achieve the following:

  • if user has acknowledged the app before and clicks FB Log in button on my website, they get logged into the website (with website's user account associated with the Facebook user ID)

  • if user has not acknowledged the app before, on FB log in (and subscription to app) they get redirected to website's registration page. Here the form is pre-filled with user data coming through Facebook and registration process becomes easier and faster.

I'm using the code below.

<body>

<div id="fb-root"></div>
<script>
    window.fbAsyncInit = function() {
        FB.init({
          appId: 'xxxxxxxx',
          status: true,
          cookie: true, 
          xfbml: true,
          oauth: true
        });

        FB.Event.subscribe('auth.login', function(response) {
              if (response.status === 'connected') {
                    var uid = response.authResponse.userID;
                    var accessToken = response.authResponse.accessToken;

                    if ((parseFloat(uid) == parseInt(uid)) && !isNaN(uid)) {
                        $.ajax({
                            url: '/user_actions/prep_facebook_registration',
                            cache: false,
                            type: 'POST',
                            data: { 'uid': uid, 'token': accessToken },
                            dataType: 'json',
                            success: function(data) {
                                if (data.success=='true') {
                                    if ((typeof(data.redirect) != 'undefined')) {
                                        window.location=data.redirect;
                                    }
                                }
                            }
                        });
                    }
              }
        });

        FB.Event.subscribe('auth.logout', function(response) {
            FB.getLoginStatus(function(res) {
                if (!res.authResponse) {
                    window.location='/access/logout';
                }
            });
        });

        FB.getLoginStatus(function(response) {
          if (response.status === 'connected') {
            var uid = response.authResponse.userID;
            var accessToken = response.authResponse.accessToken;
            //not doing anything so far
          }
        });
      };
            (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 = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
      }(document, 'script', 'facebook-jssdk'));
</script>

LogIn button lays further down in a website:

<div class="fb-login-button" autologoutlink="true" data-show-faces="false" data-width="166" data-max-rows="1" style="position: absolute; top: 5px; right: 0;" scope="email"></div>

The problem here is that FB.Event.subscribe('auth.login') triggers not only on FB log in button click, but also if user has logged to Facebook and only after comes to my website. This causing a redirection to registration page or current page reload even if user hasn't clicked the login button!

'/user_actions/prep_facebook_registration' holds a script, which is checking if the member has to be redirected to registration page or should be loggedin with local account. It returns the URL to redirect.

What am I doing wrong? How can I avoid FB.Event.subscribe('auth.login') being triggered outside the login button click?

like image 864
Aidas Avatar asked Feb 02 '12 10:02

Aidas


2 Answers

Actualy, there's a better solution.

There are 2 things that you could do better:

  1. In your FB.init method, you're setting status: true. This tells the page that it should check whether the user is logged in the facebook immediately after page loads. In your case, it's not only that you don't need it - it will take some of your visitor's bandwidth for round trip to facebook that you don't actually need.
  2. You don't need to remember uid and accessToken variables since you can get them on demand by using FB.getLoginStatus method.

The complete solution based on your sample code would be:

<div id="fb-root"></div>
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId      : 'YOUR APP ID',
      status     : false,
      cookie     : true,
      xfbml      : true
    });
  };

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

   function Facebook_login () {
      FB.getLoginStatus(function(response) {
         if (response.status === 'connected') {
            var uid = response.authResponse.userID;
            var accessToken = response.authResponse.accessToken;
            if ((parseFloat(uid) == parseInt(uid)) && !isNaN(uid)) {
               $.ajax({
                   url: '/user_actions/prep_facebook_registration',
                   cache: false,
                   type: 'POST',
                   data: { 'uid': uid, 'token': accessToken },
                   dataType: 'json',
                   success: function(data) {
                      if (data.success=='true') {
                          if ((typeof(data.redirect) != 'undefined')) {
                              if (data.redirect=='current') {
                                  location.reload();
                              } else {
                                  window.location=data.redirect;
                              }
                          }
                      }
                   }
               });
            }
         }
      }
   }
</script>

<div class="fb-login-button" onlogin="Facebook_login()" autologoutlink="true" [parameters]></div>
like image 84
Ivan Ferić Avatar answered Sep 28 '22 00:09

Ivan Ferić


=====================

Edit: Ok, I think there's a bit of a progress here :)

I've extended the FB login button with onlogin event which calls a JS function Facebook_login()

<div class="fb-login-button" onlogin="Facebook_login()" autologoutlink="true" [parameters]></div>

I've exported uid and accessToken variables outside window.fbAsyncInit function so I could access them from anywhere else:

var uid;
var accessToken;

window.fbAsyncInit = function() {
   FB.init({
      your parameters
   });
});

Then, I got FB.Event.subscribe('auth.login') to only assign values to my uid and accessToken variables, but not perform any redirection.

FB.Event.subscribe('auth.login', function(response) {
  if (response.status === 'connected') {
    uid = response.authResponse.userID;
    accessToken = response.authResponse.accessToken;
  }
});

And finally, my custom function Facebook_login () fetches the uid and accessToken values and does the rest of the operation. This time it happens only when login button is clicked. Please note, this function is outside window.fbAsyncInit()

function Facebook_login () {
          if ((parseFloat(uid) == parseInt(uid)) && !isNaN(uid)) {
                $.ajax({
                    url: '/user_actions/prep_facebook_registration',
                    cache: false,
                    type: 'POST',
                    data: { 'uid': uid, 'token': accessToken },
                    dataType: 'json',
                    success: function(data) {
                        if (data.success=='true') {
                            if ((typeof(data.redirect) != 'undefined')) {
                                if (data.redirect=='current') {
                                    location.reload();
                                } else {
                                    window.location=data.redirect;
                                }
                            }
                        }
                    }
                });
            }
      }

This seems to do a job for me. If anyone has any better solutions, your input would be appreciated :)

like image 25
Aidas Avatar answered Sep 27 '22 23:09

Aidas