Coding, is? Fun!

Friday, July 10, 2009

A concept in Facebook security

I have worked with a couple of Facebook apps since the platform was introduced. When working with developers, I have noticed that an explanation of a simple facebook security fundamental is missing. That fundamental concept helps in understanding what is possible and what is not possible very well. You do not have to check the API every time to understand it.
You may have uploaded files to a webserver. Have you noticed that there always needs to be a file upload button in HTML? You cannot automatically upload a file using Javascript. The reason is obvious - certain actions require user permissions in the browser. Unless the user explicitly clicks a button you cannot take some actions.

The Facebook security model has a simple concept like this:

The User Context
Let us take the case of getting a list of the user's friends. This is private information for the user. Therefore, the API call that gets a list of the user's friends needs the user's action to execute.
That is, you CANNOT get a user's friends unless the user is online in Facebook and explicitly clicked a button. If, on the other hand you DO want an app to perform this functionality, of getting a user's friends WITHOUT the user being online (say in the case of a batch job), you need to ask the user for an OFFLINE permission. This permission is not granted by default - it is an extended permission.
Facebook API calls are actually callbacks. When user clicks a button, Facebook sends the request to the third party app's website. That app then calls the facebook API back to get some information. Logically, even though an app is in a different web server, we can view the action from clicking a button, to the application's response as a single thread. This thread has the user's context (in the form of a TEMPORARY session id).
Thus, if you looked at the API call for getting an user's friends it does NOT usually take a input user id. It takes the current session key.
In the absence of a current session key, you can pass in a input user id, but the app needs to have the extended permission.
This applies to most API calls and it is a very easy concept to understand. In effect, Facebook is restricting you from using the Facebook user id as if it is a general database query identifier.

Scenarios

Let us take an example scenario your client comes to you with: User A visits the application canvas page and schedules a message for all his/her friends. That message should be sent only at midnight of User A's birthday. So the client wants you to store the user's request and then execute a batch job at the scheduled night to send the message to all friends. Can you do this?
The answer is you can't - without extended permissions. When your batch job executes at the middle of the night, it needs to get a list of User A's friends. For that it will call the Freinds.get API above. That API call WILL fail - because you are NOT getting the user's friends in the user's context. The user is neither online nor did they actually execute an action in the facebook app page. So, without the user's context, your call will fail.
Faced with this situation, I have seen developers suggesting workarounds - like storing the user's temporary session key in the database. My advice is GIVE UP! That restriction is there for protecting the users and you should not violate it. If you try to find a loophole, you will keep searching.

Let us consider another scenario - user enters a comment about a movie in the Flixster app. It goes to a moderator, who checks if the comment is appropriate. Then the moderator clicks the approved button - the client now wants the user's comments to be posted in the user's feed. Is this possible?
Again, the answer is no (unless the app has extended permissions). The moderator is NOT the original user. Think about it - would you like it if another user in facebook started posting entries in YOUR feed? You wouldn't. Therefore facebook does not allow (by default) an app to make entries in the feed outside the user's context.
Remember, this is different from the app itself asking you if it can post an entry in your feed. That will be allowed - because the app is still ACTING in the user's context.
Do you see the difference between the above two scenarios?
Let me explain again - let us say you take a Quiz. At the end of the quiz, the app prompts you if it can make the results available in your feed. This is fine, there is no violation of security. That is because the app is still having your session key available. You are online and you click a button. Facebook now allows the app to post an entry in your feed. The reason is because this is NO different from you posting it yourself. There is no extended permission needed for this case beyond the default permissions granted to an app.
What Facebook will NOT allow (without special permissions) is the ability of an app to post an entry to your feed OUTSIDE your user context - such as from a moderator's session.

In other words, Facebook allows apps to perform actions that the user can do when he/she is online. It does not allow apps to perform such actions on an user's network when the user is not online or from another user's session.

So, all that you have to do when a client comes up with a requirementis to ask yourself whether the action is within the user's context. If not, check extended permissions. Ideally an app should not have to operate with extended permissions. That is bad design.
Check out about Facebook's extended permissions here. You will see, for example, that an application can send Notifications when user is offline, but it CANNOT send Emails to user's inbox when user is offline (such as, through a batch process).

More information on Facebook Authorization is here.

Labels: ,

Saturday, January 19, 2008

Developing Facebook Widgets

Facebook.com is one of the earliest social networking sites that opened up for third party applications. In this tract, I will try to explain how a basic Facebook application works.

What is Social Networking

Facebook is a social networking website (among many such as MySpace, Orkut) - it allows users to be part of a community. They can communicate with each other through a profile page. A user's profile is typically public, or exposed only to friends or completely private. Users can share videos, photos and other information through the community.
This simple concept (in an alternative view) means users have an online "persona" - an anonymous personality where they can network with other people around the world with like minds. Facebook's founder calls this a "social graph".
There are specific social networking sites that allow business networking - LinkedIn is one such site. Being a member in Linked In, you can network with other people in the same business and even get references from your coworkers.


Why Facebook Applications are important
Facebook was one of the first social networking sites that allowed third party applications to be exposed through Facebook. This is a very strategic move. What do we mean by third party applications?
Let us take a chatting application. In a social networking site, live chat is not typically inbuilt. Users have to use their own Instant Messaging clients. So, it is a service that facebook users would love to have.
Now, Company A is creating a chat application by itself. It is trying to attract web users to use its IM.
Facebook brings Company A and facebook users together by allowing Company A to expose its chat application through facebook.
Company A creates a facebook "application" or "widget". This application follows facebook's standards and will work well within facebook. (We will cover details of this later).
Users can add a facebook application to their profile. Now when a bunch of users add the chat application, they can send invites to their friends to add it also. Thus, if an application is good, it can spread very fast - this is called "Viral Marketing" or the "Viral Spread". Such users may very well be interested in downloading the independent IM client.
Thus Company A has very quickly attracted loyal followers to itself with a simple widget.
The facebook widget model has its limitations but it has lots of potential. Facebook itself has a few default widgets, such as Photo sharing and Events sharing. You could very easily search for other widgets; check their popularity; read reviews about them; and then add them to your profile.
For example there is a very popular widget for film reviews called Flixster in Facebook. It allows you to share movie reviews and also rate movies. Blockbuster, the popular video rental chain in the United States has its own facebook application.
(I use the terms facebook application and widget interchangeably - facebook calls them applications but the more standard industry term is widget)

The broader meaning of Facebook applications
Although facebook applications are very popular and useful, they cannot really be shared with other websites. Google is coming up with a widget standard called "Open Social" that will help different vendors to share widgets.
The race is on between facebook style widgets and OpenSocial style widgets.
This enables and revolutionizes social networking and web marketing - it fulfills the promise that different social networking siets can talk to each other and widgets will be portable across sites. That implies that users will finally have a single addressable online presence and be able to conduct all their online interactions through such networks and widgets. It means a different development model for vendors.

The anatomy of a facebook widget
The rest of this article details how you could implement a simple facebook widget.
Let us say Company A wants to develop a widget for Movie rating. They would like users to share their reviews with each other and rate such movies. What would Company A have to do to develop such a facebook widget?
First Company A needs a web server that hosts their widget web services and a database server that hosts their application database. The webserver can be Apache or IIS or any other stack. Company A can pretty much develop the applications in any server side language - .NET, Java, Perl, PHP, Python or Ruby. It does not matter. And of course, any database server.
Let us say Company A is hosted in www.companya.com.
In the development of this application, Company A needs to show information to users in their profile page. If a user adds this application,
- they will see the widget's view in the profile page
- Movie rating or reviews can be done from the widget's "canvas" page.
The programming needs for the profile page view and the canvas page view are different.

The first few steps to facebook development are:
a. Add the Facebook Developer Application to your facebook profile. This helps you register and obtain the keys.
(See: http://developers.facebook.com/get_started.php)

b. Register your application with facebook by supplying a callback url (ex - www.companyA.com/movies/process.php) and a brief description of the application so that users can search for it and add the application.
b. Download the facebook api wrapper in your language of choice. This also comes with a sample application.
c. Create an application key and a "secret key" from facebook - the api needs this for recognizing your application.

Take a look at this page for the facebook API documentation and the anatomy of a facebook application.

1. The Canvas Page View
In the canvas page, the user will see a list of movies that have recent reviews. the user can add comments to the reviews. They can enter thir own reviews using (say) a rich text editor.
When a user views the canvas page (they reach it by clicking on the application name in their list of applications), facebook actually internally calls your registered callback url (www.companyA.com). Your web server recieves the request and you are free to serve any page view you want. (That is, facebook proxies for you). Facebook, while rendering your returned HTML, parses and manipulated the Javascript, links and other DOM elements in the page. Other than that, the page is displayed with your themes. It is rendered within the facebook window.
(The other alternative to such "proxying" is, of course, to use iframes in the page. This is the approach that Open Social takes).

Thus the canvas page view is synchronous - facebook actually calls your url and renders back the page returned by you.
When facebook calls you, you can save the review entered by the user in your database. Facebook supplies the facebook user id of the user. You can retrieve additional information from facebook itself by calling facebook's webservice API. We will later see an example of where you will need this.


2. The Profile Page View
The profile page of the user is unique and it has certain safety requirements - facebook knows that the profile page of the user is shared by many different applications. Therefore facebook does NOT call your server when it renders the profile page.
In our movie rating example, when a user views their profile page, let us say we want to show them a set of comments on their reviews. The problem is facebook does not call companyA.com when it renders the profile page. Therefore, we have to "deposit" the profile page view of an user when anyone enters comments on their review. We have to call the facebook API call set_profile_FBML and pass in the markup to show.
Facebook takes that deposited markup (called FBML because it has a slightly different set of tags than HTML) and displays it to the user when they hit their profile page.
To show accurate, on time information 9such as stock prices) in the profile page you have to set up a different kind of call back.

Thus, you can see that the interaction involves going back and forth between your web server and facebook.
In the canvas page, face book calls your server and you may in the background, call the facebook API back and then return information to the user. (Calls to the facebook API can be slow).
In the profile page, facebook takes the deposited FBML from its own database and shows it to the user. While processing that FBML, it may call back your web server.


For longer running interactions, it is also possible to run background services that can call the facebook api using an "infinite session". By default, facebook API is called under a user's credentials (context).
Storing certain types of information from facebook API (such as an user's friend list) is illegal.
Facebook's API has frequent changes - be on the lookout for breaking changes by monitoring their newsletter.

For more information:
- There is a facebook developer toolkit in .NET in Codeplex - here.
- The facebook wiki and API documentation is here
- For information on Open Social please see here.

Labels: , ,