Detect changes to the Facebook session

The look of my site depends heavily on whether the user is logged in via Facebook and resultantly, it is very important for me to detect any changes in the Facebook Session as soon as they occur in order for me to adapt the look of the page to reflect the users login status. I hate using intervals and timeouts for this sort of code as things can get really messy, but it appears to be the only option (to the best of my knowledge).

I have tried using the FB.subscribe(auth.statusChange), but this does not seem to fire regularly enough and necessarily correctly. Maybe I am using it wrong?

The way I have tested the FB.subscribe(auth.statusChange), is simply logging each time it is fired and intentionally logging in and out of Facebook on another tab. It seems that it takes around 30 minutes for the event to actually fire (and it does not always fire). Not only is this very hard to test as I have to wait 30 mins each time, it seems it does not necessarily fire correctly. Am I using it incorrectly?

The code I am thinking about using is something like this but I am not to happy with it as it uses timeouts/intervals:

window.fbAsyncInit=function(){
    // Initialize the Facebook object
    FB.init({
        appId:"123",
        status:true,
        cookie:true,
        xfbml:true,
        oauth:true
    });
    // Check the Facebook session status every 30 seconds
    setInterval(function(){
        FB.getLoginStatus(function(a){
            // Change the page look based on the facebook status
            fb_welcome(a.status)
        },true)}
    ,30000);
};

Alternatively, I would rather use a timeout instead of an interval, but this requires me passing the Facebook object to another function like this:

// Check the Facebook session status every 30 seconds
setTimeout(function(){
    // Pass the Facebook object to the welcome function
    fb_welcome(FB);
,30000);

Is it a bad idea to pass the FB object to another function outside of the fbAsyncInit function?

Answers:

Answer

Actually it is better to subscribe to auth.authResponseChange event. This is listed on Event.subscribe documentation as best practices.

For most cases, you will want to subscribe to auth.authResponseChange rather than auth.statusChange. The response is returned as a javascript array, not encoded as JSON.

Update:
Seems like this will not work for you as well, since it's called from time to time if you do calls to Facebook's API and probably in other cases like login/logout.

What you demand is not really exists in Facebook JS-SDK, and intervals seems to be an option. You can set an interval that will only call to FB.getLoginStatus and leave the event subscriptions as is since if the status/authResponse changes are detected events will be fired.

FB.Event.subscribe('auth.authResponseChange', function(authResponse){
  // authResponse changed
});

window.setInterval(FB.getLoginStatus, 30000);
Answer

I´m having exactly the same problem.

I´m not a big fan of the 30 s interval since I would have to ping my server also to know the status of my user in my site because I´ve facebook users and regular users and also because maybe it is not necessary depending on the user action (actions rely on facebook, others no)

So, I´m aiming to do the getLoginStatus in javascript only when the user asks for an action that actually needs to call Facebook on the server side

I´m using FB Javascript SDK in conjunction with the PHP SDK.

So I think I will do

  • in FB.Login : if connected then do server side authentication and I set a timeout when the token expires to do a getStatusLogin only to refresh the token
  • Since the auth.statusChange event seems to fire only on page load I will implement the actions depending on the user state in my site at this moment (page load).
  • When the user asks for an action that needs FB interaction -> getLoginStatus

The only problem I see is that it will slow down user response. What do you think of my concern about my server load every 30s x num of users ?

UPDATE

  • Since the most anoying thing was the token expired I will only implement the automatic refresh of the token thank´s to the setTimeout in javascript calling getLoginStatus
  • For the rest I will stick to a simpler solution which is a nice server error page on Facebook Exception asking to reconnect if :
    • they have logged out of facebook outside my application ,
    • they have unauthorized my app (so they don´t want to use it anyway).

In my case, those two possibilities are much more anecdotic than the first one (token expiration). so KISS

Answer

A solution applicable to more modern browsers would be to take advantage localStorage events to propagate state change between your browser tabs.

Subscribe to auth.authResponseChange and update localStorage to reflect status:

FB.Event.subscribe('auth.authResponseChange', function(authResponse){
  window.localStorage.setItem('fbstatus',authResponse.status)
});

Subscribe to localStorage change

window.addEventListener('storage', function(storageEvent){
    // this event will be fired in other tabs (not the originating tab)

    var fbStatus = window.localStorage.getItem('fbstatus');

    // take action based on the status

}, false);

Note that storageEvent parameter also contains data about the event that can be examined directly instead of always checking the fbstatus value in localstorage on any storage event:

storageEvent.key //check if 'fbstatus'
storageEvent.storageArea // the storage object
storageEvent.oldValue
storageEvent.newValue

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.