Safari ate my cookie!

If you are a developer dealing with iframes and cookies, then you would probably know this, but if not, then here is something to think about:

If website A (site-a.com) is hosting an iframe whose url is website b (web-b.com), and website B attempts to write a cookie – either via HTTP headers or javascript – it will work on Chrome and Firefox but not Safari (and IE actually).

*Note : The scenario described above is only true for the default settings of each browser. Unlike Chrome and Firefox, Safari by default sets its privacy setting to ‘Block cookies from third parties and advertisers. Obviously setting your privacy settings to ‘always accept cookies’ will mean that you won’t encounter the problem described above.

There are solutions / hacks that bypasses Safari’s privacy settings (like posting the iframe to itself) but sooner or later these loop holes will be fixed and closed by Apple. Perhaps this doesn’t affect you, since your application doesn’t rely on cookies (say for example a static html or image) however for the rest of us – this behaviour is bad news.

But what about HTML5′s localstorage? Why don’t we use that instead? Well, if the use of cookies is controlled by your application – i.e. you need to store “remember_me=true” locally on the client browser – then localstorage would be a good place to do this. However, that doesn’t solve all the issues as there are other types of cookies that are transparent to your application. Let’s look at 2 examples.

1) Session cookies – If you’re using a dynamic programming language that supports sessions (like jsp / php / asp / etc.) then the server will most likely insert a session cookie seamlessly on your behalf (i.e. a JSESSIONID or PHPSESSIONID).

2) Load Balancer cookies – Most load balancers (physical or cloud based) use cookies to track and manage a persistent connection. The load balacer will seamlessly add an extra cookie to the HTTP response (i.e. X-Mapping-abcdefg) which is used to determine which server to route all future requests to.

Putting the above into context, if your session-dependent web application is spread across multiple servers via a load balancer and is situated within an iframe in another domain, then any new Safari user visiting that site for the first time will have:

a) a different session id each time – since the session id cookie was blocked by Safari’s default privacy setting

b) a different server serving its requests each time – since the load balancer’s x-mapping cookie was blocked by Safari’s default privacy setting

This will then lead to unexpected behaviours like being logged out repeatedly or session data inconsistency (i.e. data across different servers is different). So how do we go about fixing this issue? Well, there are some work arounds available on the interweb. However, a workaround is only a short term solution and will work only until All Mighty Apple decides to shut it down. Therefore the best solution to this is to know the limitations of Safari (and its iOS webkit browser cousins) and then architect your applications to expect the behaviour where cookies can not be stored. For example, use localStorage where applicable, or don’t depend on the use of cookies, or don’t use iframes, or even better – inform users Safari’s not supported. :)

Let us know what you think of Safari and its default privacy settings.

@munwaikong

Development