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
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.
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
Related
We have a Facebook app, and through it we pull in posts and images from our company's Facebook account to an interface for later use, with the old API. Several people in the company use this interface.
We're upgrading to the new Graph API and since there are many people using the interface, I would like to generate an access token from a single user's login credentials in the background, without the whole login URL and window. We are using the PHP SDK.
Is it possible to log in a user programmatically on a button click, for example, and continue with API calls? Or will every user need to login with the popup window to be able to import posts? I assume I would then need to send in the login credentials and permissions array as well...
I've tried to add in the access_token here:
$facebook = new Facebook\Facebook([
'app_id' => {app-id},
'app_secret' => {app-secret} ,
'default_access_token' => {access-token} ,
'default_graph_version' => 'v5.0',
]);
// Can you get around the redirect with JavaScript helper here instead?
$helper = $facebook->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 'Unauthorized';
} else {
// This is the response I always get sending in the access_token
header('HTTP/1.0 400 Bad Request');
echo 'Bad request';
}
exit;
}
Auto-Login without user interaction is not possible, that would be a major security issue. You have to authorize as a user who is logged in.
You can only create an Extended Page Token as a user who manages the Page and store it - it will be valid for about 60 days.
Alternatively, you can apply for Page Public Content Access and just use an App Access Token - that is, if the Page is not restricted by age or location.
Regards,
Back, when "Authenticated Referrals" not depreciated, if the user entered to my facebook application through the canvas url, was redirected to dialogue authorization (for permissions).
Now that do not exist the option, I must do it manually so you can redirect url through the canvas.
I am using Codeigniter for it and from what I see, facebook cancel any redirection I do.
Here is my code:
try {
$fb_id = $this->facebook->getUser();
if ($fb_id) {
$fb_data = $this->facebook->api('/me');
return $fb_data;
} else {
echo 'You don't give me the permissions';
$url = $url = $this->facebook->getLoginUrl(array(
'scope' => 'email,user_likes,user_about_me,publish_stream,user_birthday',
'redirect_uri' => $this->config->item('app_name')
));
header("location:$url");
redirect($url, 'refresh');
}
} catch (Exception $exc) {
echo $exc;
}
Is there a simpler way to do it? Any examples you can show me? Thanks in advance
NOTE: My application is a (for now) recorder audio for users
First is a registration with personal information.
Then show the recorder audio.
My target is when a new user find my application (apps.facebook.com/my_app), enter to my app and show automatically the oauth dialog for permission (as before). Then enter to the registration view.
This has nothing to do with codeigniter, just make sure that your redirect_uri is your canvas page URL "apps.facebook.com/app_name".
And then use Javascript to redirect the user to the OAuth dialog with something like:
echo("<script> top.location.href='" . $url . "'</script>");
also check out the Canvas Tutorial.
I got some problem with my testing app
$params = array(
'scope' => 'read_stream, publish_stream'
);
$loginUrl = $facebook->getLoginUrl($params);
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
This is the code I use to send user who has not logged in yet to login
via facebook auth dialog.
The problem is after login using facebook auth dialog
user will be redirected to my site which is not in facebook app.
How can I send user back to facebook app after login using auth dialog ?
Please help
You can use the redirect_uri parameter of getLoginUrl() to tell facebook where you want to send the user after authorization ends (let it be success or failure).
There's a number of restrictions on what you can use there, basically you got three options:
URL under your application's domain.
The canvas path of the application (if it has one): https://apps.facebook.com/YOUR_APP_NAMESPACE
Any page url that has your application installed: https://www.facebook.com/PAGE_USERNAME/app_YOUR_APP_ID
By default, the php sdk takes the current url as redirect_uri. The documentation about these are under the oauth dialog's documentation of the same parameter.
Was google-ing about the same issue and found a solution,so thought might as well answer her.
simply add the following code in the main page.
$config['appBaseUrl'] = "http://apps.facebook.com/your_app_name/";
if(isset($_GET['code']))
{
header("location:" . $config['appBaseUrl']);
exit;
}
$config is the array that i pass while creating the facebook object. In this context,its not necessary to create an array though.
Okay as the title reads I've been trying to get Facebook's OAuth working on my localhost/, I've been struggling with various problems but I just don't know what's up with my latest problem, which is that the page loads, and if the user is logged in, it show's the logout URL and the UID like it should, and when I click the logout link it does log the user out from Facebook, but on redirect or reload the UID still appears and so does the logout link. Long story short, I can't seem to make my site that's running in my localhost log me out of Facebook AND on my site! Any thoughts would be a tremendous help. Here is my code
<?php
session_start();
// store session data
include "src/facebook.php";
$facebook = new Facebook(Array(
"appId" => "xxx",
"secret" => "xxx"
));
$user = $facebook->getUser();
echo "UID: " . $user . "<br/>";
// THIS WAS MY FIRST TRY WHICH DIDNT SUCCEED
// if ($user) {
// $logoutUrl = $facebook->getLogoutUrl();
// echo "<a href='" . $logoutUrl . "'>Logout</a>";
// } else {
// $loginUrl = $facebook->getLoginUrl();
// echo "<a href='" . $loginUrl . "'>Login</a>";
// }
// WITH THE ABOVE CODE I GET:
// An error occurred with PHP-SDK. Please try again later.
// API Error Code: 191
// API Error Description: The specified URL is not owned by the application
// Error Message: Invalid redirect_uri: Given URL is not allowed by the Application configuration.
// THIS WAS MY SECOND TRY AFTER SEARCHING FOR INFO,
// ALL I DID WAS MANUALLY ADD THE
// REDIRECT URI AND ADDED ? , THE REASON IS IF I DIDN'T ADD IT,
// IT WOULD GIVE ME AN CSRF ERROR
// STATING THAT THE STATE VALUE IS NOT CORRECT, I SEARCHED FOR THE SOLUTION
// FOR THAT PROBLEM WITH NO LUCK SO I TRIED THIS
if ($user) {
$logoutUrl = $facebook->getLogoutUrl();
echo "<a href='" . $logoutUrl . "'>Logout</a>";
} else {
$loginUrl = $facebook->getLoginUrl(Array(
"redirect_uri" => "http://localhost/php-sdk/index.php?"
));
echo "<a href='" . $loginUrl . "'>Login</a>";
}
// WITH THE ABOVE CODE I NOW GET A UID AND THE LOGOUT URL DOES APPEAR, BUT ONCE I CLICK IT
// THE USER IS LOGGED OUT LIKE HE SHOULD BUT THEN ON REDIRECT OR RELOAD THE UID STILL
// APPEARS AND SO DOES THE LOGOUT LINK, EVEN THOUGH THE USER IS NOT LOGGED IN!!
?>
It's because of facebook sdk store's the user id in your PHP session, and the logout process that takes place on the facebook's server can't clear that for you. You can see what's saved in session by checking the output of var_dump($_SESSION);
To detect if the uid stored in your session still logged in you could try using the SDK object to fetch something from the graph api, like ($facebook->api('/me')) and catch exceptions, and clear the session if they occur.
One other solution could be to add a next to the getLogoutUrl() call (just like in the getLoginUrl()) and when facebook sends the user back to that url, you clear the session variables. The default facebook implementation has destroySession on the BaseFacebook class (for some reason not listed in offical sdk docs).
I know there are many Q&A on here about this but I can't seem to make sense of them because they don't show full code examples or are for doing something different than what I'm trying to do.
I have a simple facebook welcome-test tab. Not a canvas app. I want to be able to get the users id but have to make it prompt them for access to that info before it will show up in the signed request.
So what I'm looking for is a code example for a simple welcome tab. I don't need a login page or anything like that since this will be in the fan content page so they will have to be logged in already. I just want that dialog box to popup asking them for permission so I can get the userid.
Thanks
Edit:
I wanted to add that I just figured out my problem but it's not really an answer to this question. I figured out how to get the user id without asking the user for permission to access their profile. It was as easy as adding this code to the page and it works in a tab and canvas app the same way. getUser() by its self returns 0 but since the user is already logged in to be seeing this content, when getUser() returns 0, then the code simply gets the user id from the API method. Now that I finally figured this out it seems simple.
$session = $facebook->getUser();
if (!$session) {
$url = $facebook->getLoginUrl(array(
'canvas' => 1,
'fbconnect' => 0
));
echo "<script type='text/javascript'>top.location.href = '$url';</script>";
} else {
try {
$uid = $facebook->getUser();
$me = $facebook->api('/me');
$updated = date("l, F j, Y", strtotime($me['updated_time']));
echo "Hello " . $me['name'] . "<br />";
echo "You last updated your profile on " . $updated;
} catch (FacebookApiException $e) {
echo "Error:" . print_r($e, true);
}
}
I'd still like to know if there is a way to make the extended permissions dialog show for a tab app so it will be good to see solutions for php sdk.
you need to prompt them for allowing your application to pull data on the user
this can be done using the JS SDK's function FB.login(). you can have more details in the facebook documentation : http://developers.facebook.com/docs/reference/javascript/FB.login/
notice that the popup can be opened only on mouseclick or keyup events - otherwise popup blockers will block it.
you will also have to set a domain and site url to the application in the developers site, and init the facebook js library (the loading paragraph in - http://developers.facebook.com/docs/reference/javascript/)
<div onclick="login();">click here to login</div>
<script type="text/javascript">
function afterLogin(){
alert("user logged");
}
function login(){
FB.getLoginStatus(function(response){
if(response.status=="connected")
{
afterLogin();
} else {
FB.login(function(response){
if(response.status=="connected")
{
afterLogin();
}
});
}
});
}
</script>
I don't think facebook allows this... Facebook does not want a user's tab to be able to detect who is looking at it, and possibly displaying information to a user's friends that isn't displayed to the user.
I can be wrong :)