Caching strategies for authenticated data


#1

Hi,

I’ve read through the article series on caching APIs, but one thing that seems rather conspicuously left out is strategies for showing data from APIs where different users are allowed to see different things.

Does anyone have some guidance on how to do this securely? In my case, the API calls are cookie authenticated, or else I could probably cache on a per-API-key basis. I’m not sure how to vary on this sanely.


#2

Good question, Ian. I’ve been working on a similar project. The route we’re going is a mix of a backend request to our authentication/authorization service (via something like https://docs.fastly.com/guides/vcl/authenticating-before-returning-a-request) + Vary and ESI, where it makes sense.

Although all of our requests are “authenticated” via an access token or API key (whether logged in or logged out), most of the responses are the same across users. The variations or user-specific uniqueness comes down to:

  • Response data can differ by requesting IP/country
  • Logged in requests contain a response header with the user id
  • Some responses include user-specific embedded data

For the first case, we are using Fastly’s GeoIP feature to set a header and then Vary on it. For the second, our auth backend request returns this header value. For the last, we’re using ESI (https://www.fastly.com/blog/using-esi-part-1-simple-edge-side-include).

Would be curious to hear solutions others are taking here!

Kevin


#3

You can leverage Fatly’s cryptographic functions, like digest.hmac_sha256(key, message), have shared secret key between your servers and VCL and use any user’s info as message - id, email, id+password, etc.
Generate it on server and store result in user’s cookies, and compare it in VCL every time you want to verify authentication and redirect him to some error/login page if failed.

If you have different access levels, it might get complicated. Yet, you can still have it in single cached bucket like this:
Have separate cookie that lists API’s that user can access.
Have authentication cookie = hmac(secret_key, user_id + api-list)
When accessing some API check that it’s in the API list cookie AND that and verify authenticity of API list by comparing HMAC.

The only problem with this approach, is that there’s no easy way to remove access from some API.


#4

If you include a timestamp in the authenticated hash, you can limit how long a token is valid before having to get a new token. Combine this with @kevin’s model of lightweight re-authorization service, and you won’t have to re-generate the content in the backend for every token renewal.