FB JS SDK: обратный вызов FB.Login дважды запущен в IE 11

У меня странная проблема с реализацией JS FB-SDK. Все работает безупречно, за исключением IE 11. Метод FB.login официального JS API, который получает обратный вызов, запускает его дважды после появления диалогового окна OAuth и авторизации приложения пользователем. В первый раз он возвращает ответ с параметром authResponse как неопределенным, во второй раз он имеет все ожидаемые значения.

Я совершенно не понимаю, почему это происходит. Я дважды и трижды проверил, что FB.login нигде не вызывается дважды. Кто-нибудь когда-нибудь преодолевал этот сценарий или заставлял работать вход через FB с IE?

Он отлично работает в Edge, Firefox, Chrome и даже в мобильных браузерах: chrome и safari в iOS, Android Chrome.

Я предоставляю минимальную воспроизводимую демонстрацию кода.

### index.html

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>FB IE 11</title>
</head>

<body> 
  <div id="fb-root"></div>
  <button
    id="fblogin">
    Sign in with Facebook
  </button>

  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js'></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js'></script>
    <script  src="./script.js"></script>
  </body>
</html>
### script.js

(function($) {

  var EP = { facebook: {} }

  EP.facebook.init_was_called = false;
  EP.facebook.promise = $.Deferred();
  EP.facebook.connected = false;
  EP.facebook.emailDeclined = false;
  EP.facebook.loginRetryCount = 0;

  window.fbAsyncInit = () => {
    console.log("window.fbAsyncInit callback triggered by Facebook SDK");
    window.FB.init({
      appId: "418117192377109", // should be your app id when testing
      cookie: true, // Store fbsr_xxx cookie
      xfmbl: false,
      version: "v3.2",
      status: true // Fetch user's facebook login status
    });
    EP.facebook.promise.resolve();
  };

  // Use this to wrap any calls where we're not sure the FB api has been bootstrapped
  EP.facebook.afterFacebookInitialized = callback => {
    return $.when(EP.facebook.promise).then(callback);
  };

  $(function() {
    // Always parseFBML
    EP.facebook.afterFacebookInitialized().done(function() {
      window.FB.XFBML.parse();
    });

    if (EP.facebook.init_was_called) {
      return;
    }
    EP.facebook.init_was_called = true;

    // This only needs to be called once per full page load (on The Post and when showing login screen)
    $.getScript("https://connect.facebook.net/en_US/sdk.js");
  });

  var Facebook = function() {
      var fbLoginParams;

      if (!window.FB) {
        console.log('FB not loaded yet!')
        return;
      } else if (EP.facebook.connected && !EP.facebook.emailDeclined) {
        console.log('Already logged in to FB')
        return;
      } else {
        fbLoginParams = {
          scope: "email"
        };
        if (EP.facebook.emailDeclined) {
          fbLoginParams.auth_type = "rerequest";
        }
        return window.FB.login(function(response) {
          console.log("FB.login response: ", response);
          if (response.authResponse) {
            EP.facebook.connected = true;
            return
          } else {
            return;
          }
        }, fbLoginParams);
      }
    }

    $("#fblogin").on("click", Facebook)
})(jQuery)

Чтобы это работало, он должен обслуживаться с сервера с доменом, отличным от localhost, из-за ограничений приложения fb и обслуживаться через https. Я использовал ngrok для сопоставления URL-адреса https с моим локальным сервером разработки. Локальный сервер разработки был просто parcel, начиная с выполнения parcel build index.html, а затем parcel index.html. Конечно, вам нужно настроить FB-приложение разработчика с действительным URI перенаправления OAuth (ngrok). Помните также, что вы должны выйти из Facebook, прежде чем тестировать это. Вот результаты после входа в FB и авторизации тестового приложения FB:

введите описание изображения здесь

Вот они, 2 ответа, великолепные!

Спасибо


person tommyalvarez    schedule 18.06.2019    source источник
comment
Я не могу воспроизвести проблему только с приведенным выше кодом. Я пытаюсь скомпилировать код coffeescript в код javascript, но получаю ошибку. Предоставьте больше кодов, связанных с проблемой, включая html-коды, скрипты, полифиллы и т. д. Вы можете обратиться к нему, чтобы предоставить минимальный воспроизводимый пример.   -  person Yu Zhou    schedule 19.06.2019
comment
@YuZhou попытается создать воспроизводимый пример и вернуться с ним!   -  person tommyalvarez    schedule 19.06.2019
comment
@YuZhou Ну вот, смотрите мои правки. Надеюсь, этот минимальный пример работает для вас. Пытался использовать codeandbox, но не работает с IE11, поэтому... не оставил мне другого выбора, кроме как вставить минимальный необходимый код с небольшими инструкциями о том, как попытаться воспроизвести среду   -  person tommyalvarez    schedule 21.06.2019


Ответы (2)


Я воспроизвел проблему на своей стороне. После использования fiddler для сравнения сетевого трафика между IE и другими браузерами я обнаружил, что шаг входа будет направлен на ссылку-> https://www.facebook.com/dialog/close_window/?app_id=xxxxxxxxx&connect=0 в IE11. Вы можете увидеть, как эта страница мигает при входе в IE: введите здесь описание изображения В других браузерах этого не произойдет. Я думаю, что это причина двух ответов. Это может быть какая-то проблема с IE, или API разработан так в IE.

person Yu Zhou    schedule 25.06.2019
comment
Можете ли вы придумать обходной путь, чтобы игнорировать первый ответ из примера кода, учитывая, что он очень похож на тот же ответ, который происходит, когда пользователь отклоняет авторизацию или закрывает диалоговое окно без предоставления доступа? - person tommyalvarez; 25.06.2019
comment
Единственный обходной путь, который я могу найти, - это поставить console.log("FB.login response: ", response); после if (response.authResponse) {, тогда ответ появляется только при успешном подключении. - person Yu Zhou; 26.06.2019
comment
Хм, это не помешает. Дело в том, что на более высоком уровне я оборачиваю это в промисы, и когда приходит неопределенный ответ, что иногда бывает в случае закрытых диалогов по желанию пользователя, я отклоняю промис и определенные триггеры бизнес-логики, которые влияют на пользовательский интерфейс. . Пользователи IE 11 никогда не смогут подключиться или увидеть согласованный пользовательский интерфейс, поскольку обещание уже было отклонено, несмотря на получение второго ответа. - person tommyalvarez; 26.06.2019

Проблема была в ошибке в facebook! Я разместил в их справочном центре сообщения об ошибках, описал проблему, и они ее исправили. Разрешение указано на испанском языке, но вы можете проверить здесь

Конечно, они не указали причину проблемы, но сейчас проверили, и она работает так, как ожидалось.

person tommyalvarez    schedule 04.07.2019