How to create a fan / like gate on Facebook? - facebook

I am trying to create a simple fan/like gate. Where you specify one content for none fans and other content for fans (if they pressed the like button). However when I run the page in the page tab it does not return a signed request and thus there is no way for me to figure out how to do it. Can someone post a tutorial, or have a fix for this? At this point I got the following code:
index.php
<?php
require dirname( __FILE__ ) . '/../api/facebook.php';
// Create our application instance
// (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => '112458478872227',
'secret' => 'X',
'cookie' => true
));
$signed_request = $facebook->getSignedRequest();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Home</title>
</head>
<body>
<?php
if ( $signed_request['page']['liked'] )
{
echo 'A fan';
}
else
{
echo 'Not a fan yet.';
}
?>
</body>
</html>
Link:
http://www.facebook.com/talkieslifestylemagazine?sk=app_112458478872227
Faceook App:
Page Tab
Page Tab Name: Home
Page Tab URL: http://apps.talkiesmagazine.eu/facebook/home
Secure Page Tab URL :empty
Page Tab Edit URL : empty

It looks like the original poster switched to using Wildfire's like gate app. But anyway...
Your server is doing a redirect before your script is run. If you put your code in a folder such as http://apps.talkiesmagazine.eu/facebook/home/index.php - but you specify http://apps.talkiesmagazine.eu/facebook/home as your url - the webserver will see that http://apps.talkiesmagazine.eu/facebook/home is a folder and redirect to http://apps.talkiesmagazine.eu/facebook/home/. That redirect doesn't preserve the POST data which carries the signed request. You can see if you put http://apps.talkiesmagazine.eu/facebook/home in your browser, it is redirected to http://apps.talkiesmagazine.eu/facebook/home/.
Changing your tab url to http://apps.talkiesmagazine.eu/facebook/home/ will fix it.
However, Facebook requires that you have your server setup for securely serving your app over https and set the secure tab url to that url. You have the Secure Page Tab URL empty, so that would need to be changed as well to have a fully functional tab.

Not sure why the signed request isn't showing for you. It's still working.
code: http://fbmhell.com/2011/06/facebook-like-gating-in-iframe-tabs/
page tab: http://www.facebook.com/snipe.net?sk=app_207328155971716
Maybe it's something in the migration settings that you have to check/uncheck? They've made some changes over the past few months.

Let's try this:
1, Create a simple php file on the app root named index.php with the following code:
<?
echo "POST check<br /><pre>";
print_r ($_POST);
echo "</pre>";
?>
2, Go to your app tab, and check what is come up.
2a, If the "POST check" message only, check the app URL on the app settings page. May be forget to close the url with / or there is a space somewhere.
2b, If the "POST check" message followed by an array structure, something wrong with your SDK implementation.

Your example is using the Facebook PHP SDK by the looks of it. If you want something a bit simpler and relatively straight forward to implement, then take a look at this Facebook Fan / Like Gate over on GitHub.
I've used it on a bunch of Facebook tabs in the past and it's served me well. There's also a 'JavaScript setup' branch with the js sdk and application config setup and ready to go.

Related

Flutter web event listener on other windows

I have a flutter web application, Im trying to implement Okta oauth2 but whenever I call the url that I manage to create with some params using DIO package I end up with having html response instead of the actual response.
The endpoint I'm calling looks like this:
https://dev-xxxxxxxx.okta.com/oauth2/default/v1/authorize?response_type=code&scope=openid+profile+offline_access&client_id=xxxxxxxxxxxxxxxxxxxx&redirect_uri=http://localhost:8080/authorization-code/callback&code_challenge_method=S256&code_challenge=Wag0u2fyeYWJHy_baK-XbMWO9H2xwUBii7R4Nvj761Y&sessionToken=20111jWBb2P2BoPIL-Atd0pk5QDImstT7EmYULPFMg2GoCGPgOrxKFl&state=X7hih1mUow&nonce=lSfF1CxmmR
Whenever I call this url it shall be redirected to another url such as:
http://localhost:8080/authorization-code/callback?code=TCifQEab0a6HwEGeWQXlDQhPm22RlyemvO5GbipASEU&state=YLi4I2P4qd
So the main point using DIO is that its returning the response of the second url which is an html flutter content.
It can be solved if DIO don't follow the redirection and give status code 302 but its not doing that.
Currently I'm trying different approach, I'm trying to open the url in a new window which immediately change to the second url.
My problem is how should I get the code from the second url and the cookies that the second url provide from the new opened window.
final html.WindowBase newWindow = html.window.open(url, "callback");
so at least how can I get the href from the newly opened window knowing that it changes after a while into the the flutter correct rout that I sat up.
Knowing that newWidnow.location.href is write only.
Okay I managed to solve that, leaving the solution if anyone faced the same issue.
under your /web directory create an html file and call it for example callback.html.
then paste this code inside it.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Auth</title>
<meta name="description"
content="Simple, quick, standalone responsive placeholder without any additional resources">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Authentication Succeeded</h2>
<h3>Close this window if it didn't close by itself.</h3>
</body>
<script>
window.opener.postMessage(window.location.href, '*');
</script>
</html>
then set your Redirect URI as follows http://localhost:8080/callback.html
So in that case whenever you get the Redirect URI from oauth2 you get it as follows
http://localhost:8080/callback.html?code=TCifQEab0a6HwEGeWQXlDQhPm22RlyemvO5GbipASEU&state=YLi4I2P4qd
which will basically call the newly created html file callback.html.
In flutter side you'll need to do the following:
html.WindowBase popupWindow;
popupWindow = html.window.open(
url,
"Auth",
"width=400, height=500, scrollbars=yes",
);
String? code;
html.window.onMessage.listen((event) {
if (event.data.toString().contains('code=')) {
code = event.data.toString().split('code=')[1].split('&')[0];
}
});
await Future.delayed(const Duration(seconds: 2), () {
popupWindow.close();
});
Which will basically open the window, then capture the url and extract it, then close the window.
I hope this helps.
Use assign on Location to redirect to the Authorize endpoint of the Authorization Server.
window.location.assign('https://${yourOktaDomain}/oauth2/default/v1/authorize?...');

Not receiving signed_request in Facebook iframe-app

I have created a Page Tab Facebook App where I want to display different content depending on the user being a fan or not. (Also called fan gate, landing page or reveal page)
For this I'm using the PHP SDK, in specific the following code:
<?php
require 'src/facebook.php';
$facebook = new Facebook(array(
'appId' => 'APP_ID',
'secret' => 'APP_SECRET',
'cookie' => true,
));
?>
And in the content:
<?php
$signed_request = $_REQUEST["signed_request"];
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
if (empty($data["page"]["liked"])) {?>
Thank you for liking our Page!
<?php } else { ?>
You haven't liked our page yet..
<?php };
// Debugging Code
echo "REQUEST:<br>";
print_r($_REQUEST);
echo "<br>GET:<br>";
print_r($_GET);
echo "<br>POST:<br>";
print_r($_POST);
?>
This works when I'm logged in with my Facebook User and when I use it on my own Page.
Meaning the signed_request is present in both $_POST and $_REQUEST.
However, when I test it with another user, there is no signed_request value in those variables..
Notes:
- I already took a look at my URL Settings in the App Configuration (300 Redirect and stuff) but this looks fine, and like I said with my User it's working..
- the signed_request is not just empty, it doesn't even exist.
Does anybody have similar issues?
I would not mind using the Javascript SDK instead of PHP if it works then, but I'm not very experienced in Javascript.
EDIT:
As i found out you always have to have a non-secure (http) and a secure (https) URL.
Even if you enter a secure URL as the standard URL, facebook will contact it using http and will then get redirected (depends on server configuration) to the https, which makes you lose your signed_request.
I just had a similar problem. In my case the problem was that in the app config i had not put a slash at the end of the tab URL which was referencing a directory (with an index.php in it). So i got a redirect to the same URL with a slash at the end and lost the $_POST this way.
signed_request is never passed via GET but POST. $_REQUEST contain data according to configuration in php.ini (request_order or variables_order)
Since you are using PHP-SDK it's better to use it for signed_request retrieval:
$signed_request = $facebook->getSignedRequest();
$liked = $signed_request['page']['liked'];
For applications running in Page Tab signed_request is always passed, so if you not get it ensure there is no redirections that omit POST data being passed.

Situation with signed_request, sessions and PHP SDK 3.0

I am making an application and on the "front" page of the Tab I get the signed_request. But when I navigate to different pages on the app it stops providing the data.
So far this work:
$signed_request = $facebook->getSignedRequest();<br />
$user_profile = $facebook->api('/me');<br />
echo $user_profile['id'];<br />
echo $user_profile['name'];
echo $_SESSION['signed_request']; // Returns the data
But when I navigate to other pages, it doesn't give anything.
It looses everything. How can I keep the data from the signed_request? Do I need to use sessions in some way?
I've found that the signed request isn't always passed to each page, so I used the following to hold that myself in the session object. I set this on the login page before I redirect to other pages in my app:
if (!isset($_SESSION["SR"]))
$_SESSION["SR"] = $_REQUEST["signed_request"];
$signed_request = $_SESSION["SR"];
Hope that helps.

Facebook App not working tihe facebook.php SDK

Not sure why this isn't working, and was hoping someone might be able to point me in the right direction.
I have a facebook tab app that should display different content depending on whether a user "likes us or not."
require_once('src/facebook.php');
$app_id = "142214XXXXXXXX"; <--this is correct just hidden
$app_secret = "31275c8895XXXXXXXX";
$facebook = new facebook(array(
'appId' => $app_id,
'secret' => $app_secret,
'cookie' => true
));
$signed_request = $facebook->getSignedRequest();
$like_status = $signed_request["page"]["liked"];
//just for testing (nothing shows up, nor does print($signed_request)
echo "the page is ".$page_id;
if(!$like_status){
echo "Please LIKE US to get this offer or check back on Sept 27";
} else {
echo '<img src="https://www2418.ssldomain.com/frightfurnace/SLOSSbogo.jpg"/><BR />
Printable Page';
}
Now, I know that the SDK is installed and working properly since it does work with the example:
http://www.frightfurnace.com/Facebook/example.php
I have also made sure I am using absolute urls in my Facebook App settings.
I am using
http://www.frightfurnace.com/Facebook/coupon.php
Same with SSL.
Any ideas, kinda stymied. All help appreciated.
Well found the answer in case anyone else needs it.
Go to your apps on Facebook
https://developers.facebook.com/apps/
Go to edit settings
On the left click Advanced
signed_request for Canvas: (Make it enabled)
iframe Page Tab: (enabled)
Under Canvas Settings make sure Canvas Type is
iFrame
Seemed to work for me.
Another thing to check: the tab/canvas url must be EXACTLY the same as required. If there is a redirect to another page, then signed request and other values will not be sent. You can check using a browser sniffer, if a call to the page responds with a 300 (301/302 etc) redirect, then you need to change to what it redirects to.
Examples:
https://example.com/ may need to be https://www.example.com/ (add www., or remove www. depending on how server is set up)
www.example.com/ may need to be www.example.com/index.php (add index.php, or the right page).
Check you are using http:// and https:// correctly in the URLs, and that https:// returns a valid page.

Facebook Application: How can I deny direct access on my server?

Is there a way to deny direct access to the application server for a facebook application?
Facebook loads the application via an iFrame src=http://app-domain/, but you can clearly view the page source and find out that domain and copy paste the URL into a browser and view the application directly.
There is this signed_request and oauth_token in the API, I was wondering how to use that or if I can use that to limit direct access to the application.
So if a user inputs in the browser your application's URL he gets redirected to Facebook.
Thank you.
EDIT:
I found a way that also works with form submission.
// Signed request
$signed_request = $facebook->getSignedRequest();
if(!$signed_request) header("Location: " . $settings['appBaseUrl']);
This redirects the browser while accessing the application directly and not through facebook.
It will not work if javascript is disabled.
<script type="text/javascript">
var isInIFrame = (window.location != window.parent.location) ? true : false;
if(!isInIFrame){
window.location = 'link-of-application-page';
}
</script>
You'll need some Javascript to detect whether you're in Facebook's frame and if you're not, redirect to it.
I found a way that also works with form submission. (Works for me, it might not work for you. Test it first.)
// Signed request
$signed_request = $facebook->getSignedRequest();
if(!$signed_request) header("Location: " . $settings['appBaseUrl']);
This redirects the browser while accessing the application directly and not through facebook.