web-dev-qa-db-ja.com

アプリがスタンドアロン状態の場合、FacebookログインがPWAアプリで機能しない

PWA webisteを構築しています。私はAngular JSを使用しており、私のWebサイトでJavaScript Facebookのログインを使用しました。ただし、ブラウザーでアプリを表示した場合、Facebookのログインは機能しています。ただし、ホーム画面にショートカットを追加してからアプリを起動するとホーム画面、FBログインが機能していません。Facebookページはロードされていますが、認証情報を入力すると、空白のページが表示されます。

これが私のFBログインコードです

var doBrowserLogin = function(){
  var deferred = $q.defer();
  FB.login(
    function(response){
      if (response.authResponse) {
              deferred.resolve(response);
            }else{
              deferred.reject(response);
            }
          },
          {scope:'email,public_profile'}
       );
  return deferred.promise;
}

Facebookのログイン画面を開いており、認証情報を入力した後、何も表示されません。アプリに戻らない。 Blank page manifest.jsonファイルで、displayプロパティはスタンドアロンに設定されています。助けてください。

19

ユーザーがログインするためのFacebook APIがログインフォームで新しいタブを開くため、これは正しい動作です。 FacebookはOAuth2ソリューションを実装し、APIを使用してユーザーを認証するためにOAuth2 Implicit Flowをアクティブ化します。同じウィンドウでログインするには認証コードを使用する必要がありますが、クライアント側のアプリケーションではユーザーが利用できない秘密コードが必要になるため安全ではありません。

新しいタブを開く代わりに、Facebookのログインフォームを使用してiframeを作成し、ユーザーがログインしたときに閉じてリダイレクトすることができます。

2
kklimczak

FacebookのJavaScriptプラグインを使用せず、独自のフローを記述します。

1)fbログイン応答を受信する静的htmlを作成します(例:/fb-login-receiver.html)。これは、postMessageを使用してログイン結果をアプリケーションに送り返します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    Facebook login completed.
    <script type="text/javascript">
    window.opener.postMessage(window.location.toString(), window.location.href);
    window.close();
  </script>
</body>
</html>

2)アプリケーションで、ポップアップウィンドウにfbログインページを開く関数を記述します。

このTypeScriptの例は、アクセストークンのpromiseを返し、ユーザーがメールアクセスを許可しているかどうかを確認します。

async loginFacebook(): Promise<string> {
    let popup = window.open("https://www.facebook.com/v3.1/dialog/oauth?client_id=**<YOUR_CLIENT_ID>**&display=popup&scope=email&response_type=token,granted_scopes&auth_type=rerequest&redirect_uri=" + window.location.Origin + "/fb-login-receiver.html", 'Facebook Login', 'width=500,height=500');
    var promise = new Promise<string>((resolve, reject) => {
      let finished = false;
      let listener = (e: MessageEvent) => {
        finished = true;
        let url = new URL(e.data);
        let hash = url.hash.substring(1);
        let splitted = hash.split('&');
        let dct: { [key: string]: string } = {};
        for (let s of splitted) {
          var spltd = s.split('=');
          dct[spltd[0]] = spltd[1];
        }

        if (dct['granted_scopes'].indexOf('email') < 0) {
          reject("Email required");
          return;
        }
        resolve(dct['access_token']);
      };
      addEventListener('message', listener);

      let intervalChecker = setInterval(() => {
        if (popup.closed) {
          clearInterval(intervalChecker);
          removeEventListener('message', listener);
          if (!finished) {
            reject('Login canceled');
          }
        }
      }, 10);
    });
    return promise;
}