Facebook Server side vs Client side (JavaScript) Graph API Libraries

I've been integrating applications with Facebook for nearly a year and during that time I've found it difficult to find reliable documentation, guides, and just a good set of best practices out there. A friend of mine recently voiced similar misgivings which spurred me to write about some of the obstacles I have had to overcome. I've aggregated information (with sources when available) about topics I've had to deal with when integrating with Facebook. I will break up these topics into a series of posts that will be published over the next few weeks.

Server side vs Client side (JavaScript) libraries

The Graph API is a definite improvement over previous API's Facebook has implemented. It's a RESTful API and intuitive to work with. There are numerous libraries that you can use to wrap calls to Graph and the most frequently used appears to be the JavaScript implementation. An implication of using the JavaScript library is that all your interaction with Facebook is actually being done on the client side. Using the JavaScript library for the Graph API is actually a Facebook best practice for one sole reason: performance and they're right. Client <-> Facebook versus Client <-> App Server <-> Facebook would have less latency, but I believe the gain is negligible and does not outweigh several concerns I will discuss in this post.

SoC Violation

When using the JavaScript library all your communication with Facebook is done on the client side tier. That means that any data you exchange with Facebook must be transformed using JS into a format both parties can consume (which will no doubt lead to bloat in your JS libraries). In a strict MVC sense, the View should not be doing anything but render itself for the user to consume. It shouldn't introduce extra boundaries that need to be crossed in order to integrate with a 3rd party system like Facebook. Instead of translating messages between the application server, the View, and Facebook, the integration point should instead be on the application server itself. This way there is only a single boundary to cross: your core business logic to an abstraction of the 3rd party system. All parameters of the integration can be defined in a controlled setting (on your server). Your application can decide the channel (means & protocol of message transmission), the message, the message's data format, and the destination. The correctness of any of these parameters cannot be guaranteed so long as the integration point lies on the client.

For example, if your client is sharing something on Facebook on behalf of your application, then the client will need to download all the information required to construct a Graph API post from your application server. The client will then pass the constructed post object to the Facebook JS library. When a call back is executed the application may now want to track whether or not the post was successful, as well as persist other attributes of the post and the user. Again, this information will need to pass through several boundaries and tiers of your application to get where it needs to be.

Data Validation

Anyone with limited experience in web development can tell you that you never trust data from the client side. When using the JavaScript library all your integration with Facebook is open to the unscrupulous sets of eyes of malicious users. You forfeit any capability to validate data being sent from the client to Facebook on behalf of your application. Again, using the example of sharing on Facebook, you likely have a set of immutable Facebook Post parameters the user should not be able to change such as call to action links, the redirection override URI, reference string, etc. In most cases, all the user should have the capability of changing is their custom message associated with the post[2]. Treat data you share with Facebook like any other data you accept from the client, validate it on the server.

Testing

When your integration point lies on the client you make your system much more difficult to test. If you want to test your application without the integration it's more difficult to mock or stub Facebook out of the picture on the client than it is on the server side. I realize that there are numerous libraries out that do allow for control over the client side layer during testing, but in my experience the tooling involved in testing an application that integrates with a 3rd party resource is much easier to setup, stub/mock, and test on the server than it is on the client.

Conclusion

Although the JavaScript library is tempting to use to facilitate a Rapid Application Development (RAD), I think all Graph API calls made on behalf of your application should be done on the server. There are numerous libraries you can use on the server side, depending on the language you use. Here's a list provided by Facebook. I usually work with .NET and would highly recommend the Facebook C# SDK. At the end of the day, the Graph API is a pretty easy REST API to use, so if you can't find a suitable drop-in solution then rolling your own adapter shouldn't involve all that much work.

Notes

[1] Post to user feed with the Graph API Post - http://developers.facebook.com/docs/reference/dialogs/feed/#graphapicall
[2] Immutable parameters in Graph API Post - It's a typical requirement of applications integrating with Facebook to have a user make an endorsement of something on their user feed. The application can not prefill or modify the user's custom message in any way (see Facebook's Platform Policies, Section IV titled "Application Integration Points", point #2). However, the content of the rest of the posts parameters can be prefilled as long as the user executed a workflow in a way that the parameters are expected to be in the post. For example, when sharing an endorsement of a product of a company, the image parameter post could be a picture of the product itself, the link parameter could be a link to a product on the company's website, and the action and description text could describe the product in more detail.