FBML – Ajax – Facebook Authentication
I finally decided to try and stop direct URL requests to pages that run my Facebook app and i came across some code in Facebook’s Dev Wiki. Facebook call it “Verifying The Signature” and you can read more about it here.
I needed my site to only show my pages if Facebook is requesting it, and not show anything or show an error when a user tries to go direct to the source.
IE: My Facebook app’s canvas page is on a sub domain like http://facebook.mydomain.com/, so when a user entered that into a browsers URL it would spit out a bunch <HTML> code. Now, this wasn’t directly an issue, but the code was all broken because most pages contained FBML which does nothing in a regular browser.
So, up til now it wasn’t a large drama until i implemented some AJAX functions and the processing pages had little to no verification on them so anyone could have made a simple form and resubmitting data very easily. Since my app contains closing dates for sections then it was quite easy to backdate submissions and really cause havoc if you so wished.
So now I’ve managed to turn the Dev Wiki Page code into a working validation function. But i had to still do some work on this code. It’s not 100% “Right in front of you” from that page.
make sure you take a look at the wiki page, but essentially, this is what it’s doing
- Remove the “fb_sig_” prefix from all of the keys.
- Sort the array alphabetically by key.
- Concatenate all key/value pairs together in the format “k=v” (omitting the signature itself, since that is what we are calculating).
- Append your secret key, which you can find by going to the Developers application and following the link for your application.
- Take the md5 hash of the whole string.
Bellow is my functioning code for the validation (Sorry about it not being formatted, My theme doesn’t format code too well)
PHP:
function CheckUser($appsecret) { $fbsig = array(); foreach($_POST as $key=>$value) { if(substr($key,0,7) == 'fb_sig_') { $fbsig[substr($key,7)] = $value; } } ksort($fbsig); foreach($fbsig as $key=>$value) { $string .= $key . '=' . $value; } $string .= $appsecret; if (md5($string) == $_POST['fb_sig']) { return true; } } function IsFacebook($appsecret) { if (!CheckUser($appsecret)) { echo "You have tried to access this page outside of facebook. Please go back to <a href=\"http://www.facebook.com\">facebook</a> and stop trying to hack our app appart"; exit; } }
This code is pasted into each page you want to run the validation on
// this is accessed from your Dev page, ONLY you and facebook should ever know this $appsecret = ############################ $facebook = new Facebook($appapikey,$appsecret); // Initiate Facebook $fb_user = $facebook->require_login(); // make sure the user is logged into Facebook first $uid = $facebook->get_loggedin_user(); // get the users details // Make sure it's facebook requesting the page IsFacebook($appsecret);