FB.login and blocking pop-ups

2

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

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

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

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

Permission check function:

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 "broken" version

Use the following construction (activated by a click of 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 link (by clicking on the Post button).

The problem

As I'm checking with permission publish_actions the popup is not directly linked to the click. Even though a click activates the stream, the call to FB.login is actually tied to a callback . Result: Browsers are blocking the login pop-up.

The undesirable solution

I can skip the first check for permissions and force a stream of login always (if the user has already granted 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 (by skipping the first permission check) the popup normally opens since the FB.login method is responding directly to the click. The downside is that it is calling the login method every time, making users who have previously granted permission handle an unnecessary and recurring overhead.

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

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

Perfect scenery

  • The user clicks Post
  • The application verifies that the user has the publish_actions
  • Application publishes photo (without requesting permission with extra permission)
  • Alternate scenario:

  • The user clicks Post
  • b) The application verifies that the user does not have the publish_actions
  • The application requests a new login with permission (this window is not blocked by the browser)
  • The user authorizes the permission
  • The application publishes the photo
  • asked by anonymous 19.03.2014 / 06:48

    1 answer

    0

    Answering my own question for future reference.

    Actually the call to FB.login has to be done directly from the click or browsers block the pop-up from login. But by reading the "Facebook login popup blocked in IE 9" in>> in SOE I was inspired to refactor my code as follows:

    At page initialization I subscribe to the event authResponseChangeCallback :

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

    This causes the callback authResponseChangeCallback to fire after the Facebook API initialization. If the user is logged in to Facebook the callback checks the publish_actions permission. The "Post" button only appears 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 autorizado property in a date attribute of the button.

    During the click on the "Post" button, instead of directly checking for publish_actions , I only retrieve the value of the autorizado attribute. So pop-up login is triggered in click context, eliminating pop-ups problem.

    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 solves the conflicts mentioned in the question.

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

  • Grant the permission
  • Access the page, which stores autorizado = true on the "Post" button
  • Sign in to Facebook in another tab
  • Delete the publish_actions permission of the application
  • Return the tab in the application and click "Post"
  • But this is such an artificial case that I initially see no problem letting the application fail.

        
    22.03.2014 / 03:55