views:

436

answers:

2

According to RFC 2109, the value of a cookie "is opaque to the user agent and may be anything the origin server chooses to send, possibly in a server-selected printable ASCII encoding."

As a consequence of this, different languages/platforms/server send a different cookie value even when the original value is the same.

For example, C#/ASP.NET send the text as is; classic ASP urlencodes and urldecodes the text; Perl/Apache urlencodes/decods the text (but differently from ASP!). Php gives you the option.

I am writing a Single Sign-On system that needs to share a cookie with wildly different applications. In particular I have .NET, Java, Perl, ColdFusion that need to be supported out-of-the-box.

The text I store in the cookie is always a valid ASCII-7 string. Nevertheless, Perl likes to encode some 7-bit ASCII characters, for example.

I see two main alternatives to make this work:

  1. Only accept non-encoded values. After all there is no need to encode them. This is how it is at the moment. Obviously all integrated systems must be able to support non-encoded values.

  2. Accept both encoded and non-encoded values. This would allow for maximum compatibility out of the box, but I would need to determine whether a particular value is encoded or not (which sounds quite impossible: is "%20" the literal "%20" string or a space?)

Which solution would you suggest and why? If it is #2, how would you detect UrlEncoded text?


Example of a cookie (I've added line breaks to make it fit)

A5A2794D694241AD92F9B22F288EFAA1|8428DCCC|20090821142732|20090821142832|
10.100.107.40|955098D50AB4982D4E247EFA53F4E23B32A05ED0131E096709BE1D8CCC
8A3CA18252D376473C244FD71C462AB42CF54C
+2  A: 

Yes, this is not a trivial problem. Fundamentally, I lean more for solution #2 since that is the most interoperable. However, as you say, it is quite a non-trivial problem to detect which cookies are URL Encoded and which aren't.

One thing that comes to my mind is that you can use some special characters to pad the start of your Cookie values and that way you can detect if the Cookie is encoded or not. Of course, this might not cover all the clients, but for example if your normal cookie values are of the form CookieValue1234 then you can change it to head :CookieValue1234 and check to see if the space in there will come back URL encoded or not (ie comes back as "%20" or as " ").

paracycle
Definitely the safest solution, you can put multiple test characters if you want to test several encodings too.
Mathieu Garstecki
+1  A: 

Any reason you can't a purely alphanumeric value? If you've got opaque binary data you're trying to persist, then you could either use hex or use "web safe" base64.

The less likely you make it that anyone will mess around with your cookie at all, the better IMO.

Jon Skeet
I am already using HEX. The only non alphanumeric is a pipe character to separate fields -- that's what is being encoded by perl. On the other hand, any character could be encoded for all I know under other platforms. You never know :)
Sklivvz
I think if you stick to alphanumeric, it'll be fine. Just use X as the delimiter instead of |.
Jon Skeet