0

I am relatively new to CloudFront, and my company is considering a possibility to move there. We have a bunch of webites with our own cookie-based authentication mechanism, pretty straightforward: login page sets a special cookie, all other requests served when this cookie is present, and denied otherwise.

What we wish from CloudFront is the following:

  1. When a first request to some resource contains this cookie, pass the cookie to the origin server. When there is no cookie, send the request anyway, it is ok to have access denied error returned in this case.
  2. Cache the returned result (if success).
  3. All following requests to the same resource having this cookie should be taken from cache.
  4. Optimally (but optionally), cookie expiration should be checked.
  5. Besides, usual cache-control rules based on headers should apply.
  6. Login page request may be cached or not, this is not important.

I tried to use cookie whitelist, but the cookie contents is different for different logins, so same resource requests for different users are cached separately, thus generating full traffic to our origin. The point is - CloudFront should take into account cookie name and expiration date, but ignore its content.

Is there any way to accomplish this?

BBR
  • 690
  • 6
  • 10

1 Answers1

2

No, there isn't. Here's why:

When a response is stored by a web cache, the corresponding request is also stored. The cache must not consider two requests to be identical unless they are indeed identical requests.

Two requests cannot be considered identical unless they are, in fact, identical in every way, when what was sent to the origin is taken into account.

Prior to sending a request to the origin, CloudFront strips the incoming request of anything that it will not be forwarding -- headers, cookies, query strings -- and everything that remains... that is, everything that will be sent to the origin... is what will be compared, on subsequent requests.

The reason for this is that a cache is prohibited from returning an invalid response, and unless an identical request is sent to the origin, there is no way for a cache to know whether the response will also be identical; therefore, a request that results in something different being sent to the origin server will never receive a cached response that the origin returned for what was (by definition) not the same request.

This is why CloudFront allows selective whitelisting of headers as well as cookies: so that you can prune what actually gets forwarded down to only what the origin needs to see, in order to respond appropriately. The less you whitelist, the more likely a subsequent request is to actually be identical.

If, for example, you forwarded the User-Agent: header to the origin, the origin server might respond differently based on heuristics applied to the user agent (supplying different content, say, for IE than for Firefox or Chrome, to accommodate IE's quirks). If your origin needs that information, you have to forward it, and take the penalty that comes with it -- the response will only be served from cache for another user with an identical browser. If you don't need the user agent string, you don't forward it -- for this reason.

Evaluating cookies by name only would clearly be at odds with this logic. The cookie value is different, because the user identity is different, and the origin should reasonably be expected to respond differently. (Also, note that when the browser presents a cookie, it doesn't present the expiration time. That information is only present when the server sets a cookie.)

If you need to provide authenticated access to cached objects, you'll need to use one of CloudFront's built-in auth mechanisms, rather than passing the authentication/authorization through to the origin using cookies.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • Thanks for the full explanation. It is sad that CloudFront does not support what other CDNs do; as a result, our efforts double. – BBR Oct 30 '15 at 09:09
  • anyone know if this behavior is possible using Lambda Edge? I have the same problem and would be ok with the ramifications of not considering the cookie _value_ in the cache hit/miss decision. – carillonator Oct 25 '17 at 16:11
  • @carillonator yes, I believe this should indeed be possible with Lambda@Edge and a Viewer Request trigger. For any specific cookie, you want to replace its real value with a fake/static/dummy value, so that the cookie must be present but need not have a specific value? It looks like this could be done using an approach somewhat similar to the way I was able to [remove a specific cookie entirely](https://stackoverflow.com/a/45970883/1695906) using Lambda@Edge. – Michael - sqlbot Oct 25 '17 at 17:15
  • @sqlbot I actually do need the value of the cookie passed through to the origin, just not considered as part of the cache key; the returned markup is identical regardless of the value. I was thinking an Origin Request lambda could set the cookie, while leaving cookie forwarding otherwise disabled. will need to try it. thanks. – carillonator Oct 26 '17 at 19:15
  • @carillonator Did you already come up with a solution for that? I am also looking for a way to pass the cookie to the origin if there is no cache match, but ignore the cookie value to find a cache match. – totas Nov 30 '17 at 08:23
  • I described my Problem here: https://stackoverflow.com/questions/47569633/pass-cookie-to-cloudfront-origin-but-prevent-from-caching – totas Nov 30 '17 at 10:17
  • @totas no, it's not possible with Lambda@Edge, unfortunately. – carillonator Dec 04 '17 at 19:15
  • @carillonator I actually solved that problem with a workaround here: https://stackoverflow.com/a/47595474/2030937 – totas Dec 05 '17 at 12:01