FB.login and pop-up blocking

Asked

Viewed 1,757 times

2

I have a usability problem when requesting extra permissions on Facebook.

According to Facebook documentation the function FB.login should only be called after a click as most browsers block open pop-ups by any other means.

The problem occurs when I’m using the function FB.login in the middle of my application in order to request extra permissions to post an image (according to Facebook’s best practices I leave to request this permission at the last moment).

Before requesting permission I check if the user has not already granted it. Which led me to the following construction:

Function for permissions checking:

function checkPermissions(perms, callback, failCallback) {
    FB.api('/me/permissions', function (response) {
        var fbPerms = response.data[0];
        var haveAllPermissions = true;

        if (typeof perms === 'string') {
            perms = [ perms ];
        }

        for (var i in perms) {
            if (fbPerms[perms[i]] == null) {
                haveAllPermissions = false;
                break;
            }
        }

        if (haveAllPermissions) {
            callback();
        } else {
            failCallback();
        }
    });
}

The version "broken"

Use the following construction (activated by one click on a button):

  // Verifica permissões
  checkPermissions("publish_actions",
      // Em caso de sucesso cria o request
      generateRequest,
      // Em caso de fracasso
      function () {
          // requisita a permissão
          FB.login(function () {
              // Verifica a permissão novamente
              checkPermissions("publish_actions",
                  // Em caso de sucesso cria o request
                  generateRequest,
                  // Em caso de fracasso notifica o usuário
                  function () {
                      alert("Permissão negada");
                        // Reativa o botão para postar colagens 
                        $("#gerarColagem").one('click', enviaColagem);
                  });
          }, {scope: "publish_actions"});
      });

You can see the code in action http://sfcb.7rtc.com (by clicking on the Post button).

The problem

As I’m checking for permission publish_actions the pop-up is not directly linked to the click. Even if a click activates the flow, the call to FB.login is actually attached to a callback. Result: Browsers are blocking login pop-up.

The undesirable solution

I can skip the first check by permissions and force a flow of login always (if the user has already assigned the permission everything happens silently):

 FB.login(function () {
     // Verifica a permissão novamente
     checkPermissions("publish_actions",
         // Em caso de sucesso cria o request
         generateRequest,
         // Em caso de fracasso notifica o usuário
         function () {
             alert("Permissão negada");
             // Reativa o botão para postar colagens 
             $("#gerarColagem").one('click', enviaColagem);
         });
 }, {scope: "publish_actions"});

In this case (skipping the first permissions check) the pop-up normally opens once the method FB.login is responding directly to the click. The downside is that it is calling the login method every time, causing users who have already secured permission to previously handle a overhead unnecessary and recurrent.

In the happy scenario the user will grant permission the first time they click on "Post". The "broken" version ensures that these users do not go through a login flow unnecessarily; everything works correctly after the first authorization.


So my question is: How to structure my calls to make and request permission with FB.login without the browser blocking the Facebook pop-up? Is there any way to check permissions before calling the FB.login without the browser blocking the pop-up?


Scenario Perfect

  1. The user clicks on Post
  2. The application checks that the user has the permission publish_actions
  3. The application publishes the photo (without requesting login with extra permission)

Alternative scenario:

  1. The user clicks on Post
  2. b) The application checks that the user does not have the permission publish_actions
  3. The application requests new login with permission (this window is not blocked by the browser)
  4. The user authorizes permission
  5. The application publishes the photo
  • With so many scenarios, was a little confused to understand the desired scenario, exactly as you want, could edit and put in much relevance your "perfect" scenario with the behavior exactly described?

  • Paulo, I updated it in use case format. The whole dilemma of the thing is that either I implement step 2 as described and step 3 of the alternative scenario breaks (due to pop-up blocker) or I skip step 2 and log in always (ruining the perfect scenario). It became clearer?

1 answer

0


Answering my own question for future references.

Really the call to FB.login has to be done directly from the click or browsers block the pop-up login. However reading the question "Facebook login popup blocked in IE 9" on SOE I had the inspiration to refactor my code in the following way:

At page startup I subscribe to the event authResponseChangeCallback:

FB.Event.subscribe('auth.authResponseChange', authResponseChangeCallback);

This makes the callback authResponseChangeCallback is triggered after the Facebook API is initialized. If the user is connected to Facebook, the callback checks the permission publish_actions. The "Post" button is only displayed after this query:

if (response.status === 'connected') {
  FB.api('/me/permissions', function (response) {
    var fbPerms = response.data[0];
    var autorizado = (fbPerms.publish_actions != null);
    var botaoPostar = $("#gerarColagem");
    botaoPostar.data("autorizado", autorizado);
    botaoPostar.show();
  });
}

This function stores a property autorizado in an attribute date button.

During the click on the "Post" button, instead of checking directly for permission publish_actions, I only retrieve the value of the attribute autorizado. Thus, there is need to login to pop-up is fired in the context of click, eliminating the problem of pop-ups boqueadas.

var autorizado = $(this).data("autorizado");
// Usuario tem permissao para publicar
if (autorizado) {
  generateRequest()
}
// Usuario não possui permissão para publicar
else {
  // requisita a permissão
  FB.login(function () {
    // Verifica a permissão novamente
    checkPermissions("publish_actions",
      // Em caso de sucesso cria o request
      generateRequest,
      // Em caso de fracasso notifica o usuário
      function () {
        alert("Permissão negada");
        // Reativa o botão para postar colagens 
        $("#gerarColagem").one('click', enviaColagem);
  });
}

This solution resolves the conflicts mentioned in the question.

Some artificial cases may cause problems, for example, the user may:

  1. Grant permission
  2. Access the page, what stores autorizado = true on the "Post"
  3. Login to Facebook in another tab
  4. Delete the permission publish_actions of the app
  5. Go back to the tab in the app and click on "Post"

But this is such an artificial case that initially I see no problem in letting the application fail.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.