Facebook JS SDK Progressive web app issue

删除回忆录丶 提交于 2020-01-01 09:32:21

问题


I have a Progressive Web App built with Angular 4.

My Problem is the Fb login dialog does not close automatically when used from the home screen app. It works perfectly fine when opened in chrome browser but when i use it from installed home screen app the dialog window opens asks for permissions, after all permission is given the dialog goes blank and does not close or redirects back to the app.

It seems like if i change the "display" in manifest.json to "browser" it works but does not work when "display" is in "standalone".

I have searched all over but no success.

Thanks


回答1:


When your app is installed as a progressive web app, the Facebook login popup and the parent window (your app) can't communicate the way they do in a desktop environment.

You'll face this problem in other scenarios as well, e.g. when your app is launched using in-app browsers like Instagram's or Facebook's.

You can implement a server-based flow as suggested by another answer. You can also implement a custom redirect flow on the client side.

A custom redirect flow works without popups. When your user clicks a "Login" button, he/she is instead redirected to a Facebook login screen. After logging in, the user is directed back to your app using a URL that contains everything you need to verify the success or failure of the authentication.

How to create a custom redirect flow is described in the Facebook SDK documentation, under "Manually Building a Login Flow":

https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow

The idea is as follows:

You direct your users to the Facebook login dialog (not the popup launched by FB.login()), e.g. when they click a button:

https://www.facebook.com/v2.11/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &response_type=token
  &state={state-param}

If the user successfully grants your app the necessary permissions, he/she is redirected back to your app (the location is determined by {redirect-url}):

{redirect-uri}?code=<facebook-code>&state={state}#_=_

Then you app needs to figure out whether the login was successful or not. There are two ways to do this:

A) Read the query string of the current URL (see the code=<code> part -- this can be used to retrieve additional info about your user, or it can be sent to your backend server).

B) Use the Facebook SDK do retrieve the login status using FB.getLoginStatus(yourCallback)

If you're already using the SDK and FB.login(yourCallback), you can add yourCallback to FB.getLoginStatus as well. You can also support both a popup flow and a redirect flow depending on the user's device.

I suggest reading through the documentation entry I posted above for further information and options.




回答2:


I kind of figured out a way to do this for FB. Used FB PHP SDK to generate a login url and opened the url on a child window and the whole login dialog & permissions thing happens and it redirects to my redirect_url where I pass the necessary data to parent window using window.opener.postMessage.

My redirect_url page is setup like this:

<?php
if ( ! session_id()) {
session_start();
}

require_once "vendor/autoload.php";

$_SESSION['FBRLH_state'] = $_GET['state'];
$fb = new Facebook\Facebook([
'app_id'                => 'FBID', // Replace {app-id} with your app id
'app_secret'            => 'FBSECRET',
'default_graph_version' => 'v2.2',
]);

$helper = $fb->getRedirectLoginHelper();

try {
$accessToken = $helper->getAccessToken();
} catch (Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch (Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}

if ( ! isset($accessToken)) {
if ($helper->getError()) {
    header('HTTP/1.0 401 Unauthorized');
    echo "Error: " . $helper->getError() . "\n";
    echo "Error Code: " . $helper->getErrorCode() . "\n";
    echo "Error Reason: " . $helper->getErrorReason() . "\n";
    echo "Error Description: " . $helper->getErrorDescription() . "\n";
} else {
    header('HTTP/1.0 400 Bad Request');
    echo 'Bad request';
}
exit;
}

$oAuth2Client = $fb->getOAuth2Client();

$tokenMetadata = $oAuth2Client->debugToken($accessToken);
$tokenMetadata->validateAppId('FBID'); // Replace {app-id} with your app id
$tokenMetadata->validateExpiration();

if ( ! $accessToken->isLongLived()) {
try {
    $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
} catch (Facebook\Exceptions\FacebookSDKException $e) {
    echo "<p>Error getting long-lived access token: " . $helper->getMessage() . "</p>\n\n";
    exit;
}}

$_SESSION['fb_access_token'] = (string)$accessToken;
$tk = $_SESSION['fb_access_token']; 
?>

<?= $tk;?>
<script type="text/javascript">
window.opener.postMessage({token: '<?= $tk;?>'}, '*');
window.close();
</script>

In the parent window I have an eventListener which is listening to the postMessage using window.addEventListener("message", receiveMessage, false);and the receiveMessage function handles all the data as required. So any web app using standalone mode should be able to get data from child window.

Window postmessage can be used to pass data between cross-origins. More details on postMessage are here: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage



来源:https://stackoverflow.com/questions/46427462/facebook-js-sdk-progressive-web-app-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!