Wednesday, January 4, 2012

Compact Policy usage on Facebook Apps with Internet Explorer

The Problem
Most useful Facebook apps you write will be stateful, the most common way of achieving this is to allow your chosen web container to run user sessions. As HTTP is stateless, cookies are used to reunite the user with their session on each request thus maintaining state.
The problem arises when for whatever reason the browser doesn't accept the session cookie and your facebook app can't maintain state for that user. This most commonly happens with Internet Explorer, every developer's favourite browser!
In this article I dig a little deeper and look at ways to mitigate this problem.
This post relates to privacy issues and you should seek advice from your legal advisor before using the techniques I describe here in a public facing deployment.

Example
A user hits your fb app running Internet Explorer (IE) with elevated privacy settings. As modern facebook applications run within a facebook iframe any cookies issued by your webapp are not regarded as 1st party and thus subject to even stricter controls. Such cookies are usually blocked by the browser and cause your user to lose state and your app to malfunction, often sending your user to your login page.
The exact same thing can happen if your user is running 3rd party security software from some well known vendors.

Solutions
You need to either:
1) Increase the chances of your session identifier cookie being accepted or
2) Make your webapp function without cookies at all.

Solution 1.
Internet Explorer now stands alone in that it's the only mainstream browser implementing W3C's Privacy Policy framework P3P. This allows a site to specify it's privacy policy in a machine readable format and a browser to make intelligent decisions based on a user's privacy preferences.... that's the idea anyway. The fact most browsers don't implement the standard shows the industry has lost interest in this standard.
However it matters to you as the lack of a Compact Policy (derived from a Full P3P Privacy Policy) has a serious impact of whether IE is going to accept your cookies. Take a look at Microsoft's own article at deploying P3P. You will find a range of tools for generating policies on the web.

Many sites, Facebook included, contain a message in place of the Compact Policy explaining why they don't comply. JUST the presence of this is enough to persuade IE to accept your cookie.

The Compact Policy is specified in the response header. Here's what facebook's looks like:
P3P:
CP="Facebook does not have a P3P policy. Learn why here: http://fb.me/p3p"

In Java you can do something similiar like this:
response.addHeader("P3P","CP=\"Please see our privacy policy at xxxx page.\"");

You could do this easily in a servlet filter so that it effects every response passed through the filter.

I'd of course recommend issuing a real policy containing a series of the accepted shortcodes.

Solution 2:
If you really can't get your cookies accepted by the browser there is one fallback position. URL-Rewriting is a technique where the Session ID is appended to the end of each browser request. This allows the session to be determined by the container and the client reunited with their session.
This technique obviously requires all links to be rewriten to bounce along the session with every request. This approach is supported by most containers and if your using the great Spring Security it all works automatically when needed.
Note: Exposing the SessionID does have security implications beyond the scope of this article, be aware of these before you go live using this, check out OWASP. UrlRewriting can easily be disabled too.

Conclusion
Implementing one or both of these techniques is as close as you can get to ensure your facebook app works as expected.
Note: Many sites Facebook and Google included can detect if cookies are completely disabled and will simply display an appropriate error message before refusing to work, you should take this approach if solution 2 is not appropriate for your application.