Thursday, May 5, 2011

Fun with the new Facebook PHP SDK and WordPress

As I've mentioned, I started this blog with the intention of being able to claim research and development credits at work when I come across particularly hairy issues, and good news, as today I have something to write about.

Today, more and more people want social integration with their website, and who can blame them? Facebook has hundreds of millions of users and integrating that with your website can allow users to interact with your site easier than ever.

I do a lot of work with WordPress, which is a great little CMS that is flexible enough to adapt to almost any type of site, and since I can remember, I have used a great plugin from a fellow who goes by the name "Otto", called Simple Facebook Connect.

Simple Facebook Connect works great. It makes it easy to set up "Like" buttons, user registrations via Facebook, comments for users through Facebook who aren't members of your site, and more, however, Facebook has recently introduced the newest versions of their "Social Plugins", which introduce some increased functionality for the older items, and some completely new items.

Naturally, a client wanted us to implement some of these new plugins into an existing site which was built using WordPress. At first, I had hoped this would be a simple transition, however, this was not the case.

The biggest problem is that in order to use the new plugins the new JavaScript SDK must be loaded into the site. The old SDK and new SDK do not work nicely together, so in order to use the new features, we would have to rebuild all of the old functionality, while making sure the new functionality would work as well.

A lot of the problems were fairly simple to figure out. Although Facebook's documentation is notorious for being incomplete, I was able to reproduce most of the functionality needed that I would lost in removing "Simple Facebook Connect". The biggest issue with logging users in however, was that I couldn't easily just "hook" into the WordPress actions system, and needed to tell the JavaScript SDK to reload the page when a user logged in via Facebook, pointing them to a PHP file that would receive the Facebook Session as a query parameter in order to properly log the user into our site and Facebook simultaneously. This was much easier than what was to come...

Facebook specifies in their documentation that if you log a user into a site via a Facebook login, then when they log out, they MUST also be logged out of Facebook. This makes sense, so that if a user is at a public machine they won't "accidentaly" leave their Facebook account logged in for the next person who comes to use the machine.

The biggest problem is that when you use the new PHP SDK for Facebook, you're using something that's still in development, and still missing some features. In the older SDK, you could simply create a Facebook object and call a "logout()" method which would log the user out of Facebook, the new SDK didn't have this feature, and so I was out of luck.

I searched long and hard, spending between 14 - 16 hours trying to get different solutions that were mentioned online to work. The client we were doing this work for even had a contact at Facebook, who couldn't give us an answer, and could only point me back to solutions that I had already investigated.

The solution that made the most sense to me that was online was that when the user logs out, delete the cookie which is storing the Facebook session. I knew that this would work, as if I deleted the cookie manually, using my browser's cookie viewer, I would be successfully logged out of both sites, but obviously, that wasn't something we could write on the page on the way to log out.

I knew that I could hook into the "wp_logout" action generated by WordPress. This action is called when the WordPress user session has been destroyed.

Over and over I tried different ways of deleting the cookie. Setting it's content to empty, expiring the cookie, using external libraries to delete cookies (which was basically just trying to do the same things I had been trying).

I knew there was a "Facebook Logout Url" that I could grab from the PHP SDK, however, trying to redirect this would not work. However, I did find that if I was to manually hit that address, it would accept the fact that the cookie had been expired, and my Facebook account would be logged out.

I found, by going into the WordPress source, that it throws a redirect after "doing" the "wp_logout" action. This made sense. If I try and redirect to the logout url from Facebook, and then WordPress throws it's redirect, the headers would cause an error, and the cookie isn't properly cleared.

The final solution was to "exit()" the custom logout function which redirected to the Facebook URL, thus completely eliminating the call to WordPress' integrated wp_logout redirect.

There have also been some other lessons I've learned with the new Social Plugins, with the most important being that the "FB.Share" JS will cause the new JS to fail. Hopefully I'll have more on another Facebook Social Plugin issue soon!