Facebook Access Tokens from Canvas Apps
UPDATE 26/07/10: looks like the Facebook Platform team is addressing this issue presently. There's a new migration option available to send session data in the request. When I used this parameter it seems that all old session related fb_sig parameters were no longer being sent, so I'd probably avoid using this. Instead refactor your applications to use the new OAuth support for Canvas apps, which is also available to enable in the App Settings Migration tab.
There's an open bug over at the Facebook bug tracker detailing an issue people are having with Canvas pages and the new Graph API. Right now, Facebook canvas applications are posting a session_key to the canvas callback URL. The new OAuth system of course uses the access token system, rather than the session_keys from the old Rest API.
There's a bit of info hiding in the documentation upgrade guide that outlines how to "exchange" a session key for an access token. All you need to do is POST some info to an endpoint and it'll spit back a valid access token.
Like so:
$ch = curl_init("https://graph.facebook.com/oauth/exchange_sessions");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
"type" => "client_cred",
"client_id" => "<your canvas application id>",
"client_secret" => "<your canvas application secret>",
"sessions" => $_REQUEST["fb_sig_session_key"]
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch));
$accessToken = $result[0]->access_token;
So what's going on here? You're POSTing a request to the Facebook OAuth implementation to exchange your session key for an access token. You provide your application id and secret (important: this needs to be id and secret for the canvas application the request originated from of course) and the session ID of the user. Send this off and a JSON response will come back with the access token. Also, if needed, there's another property passed back - "expires", which will let you know when this access token will die.
Okay, so now you have an access token for use with the new API. Now what?
There's a little bit of fudging required to use this with the PHP SDK. The setSession() method of the PHP SDK doesn't just take an access token, it expects all the other crap that is usually contained in the cookie it saves. The idea behind my solution is that you shouldn't need to modify any base classes. The code below will con the Facebook library into accepting your newly acquired access token:
$session = array(
"uid" => "",
"session_key" => "",
"secret" => "",
"access_token" => $accessToken
);
ksort($session);
$sessionStr = "";
foreach($session as $sessionKey => $sessionValue) $sessionStr .= implode("=", array($sessionKey, $sessionValue));
$session["sig"] = md5($sessionStr."<your app secret>");
$facebook->setSession($session, false);
What this code is doing is constructing a fake session object. Since the only thing the SDK actually looks at in this session data is the access_token, we just fill the other entries with an empty str. Once this is done, we just calculate a signature for the data, as per the Facebook Wiki documentation. Again, we're only doing this because the setSession() method demands it.
Once this is done, you can go ahead and make api calls! Now wasn't that easy?
Also, as a little footnote, you should know that you don't actually have to fudge the session, you can just pass the access token you get into each api call, like so:
$facebook->api(array("method" => "stream.get", "access_token" => $accessToken));
... But this is a bit cumbersome. Also, with the fake session, you can just remove my code later when Facebook starts sending access token in the initial POST data.
You can see this solution in action at this Facebook page. Just click grant access, then click Go.
Hope this helps someone!
The Facebook Platform
Over the past few days I've immersed myself in the engaging, complex, diverse, exciting and downright confusing land of Facebook development. I'm currently writing a WordPress plugin that integrates a blog fairly extensively into a Facebook Profile Tab. With the bulk of the functionality now written, I can step back and reflect on the experience as a whole. I'm now going to post some thoughts on it.
In a word - wow. The process has very much been a rollercoaster ride, let me tell you. I picked a bad time to launch into this project - Facebook is in the process of transitioning from "Facebook Connect" to the new Graph/"Facebook Platform/Open Graph/whatever branding, bringing a slew of new APIs, SDKs, and other changes along with it. For example, right now if you visit the Facebook Developers website, they're trying to rework all the documentation, hiding the original Developers Wiki in the process, leaving a HUGE gap in the documentation in the process.
Further, right now the Platform as a whole is riddled with inconsistencies in terminology and functionality. What's worse is the transitory phase is obviously quite involved, and there's bugs all over the place.
That being said, the Platform is a pretty sexy wonderland of functionality. When I wasn't encountering odd issues or server latency dramas, it was pretty cool to work with such a diverse environment. That being said, I haven't actually worked with the Graph API much yet - the application I wrote needed to be integrated into a profile tab, which still only supports FBML/FBJS - no iframe support yet.
I'm going to be posting alot of articles here over the coming weeks/months with nifty things I've discovered and "gotchas" I've worked around in the land of Facebook. Also, I'll be putting more info up here soon for the plugin I'm developing that I mentioned earlier, currently dubbed "Faceblog" - not sure if I'm gonna have troubles with this name yet
Stay tuned!
