filipw / Strathweb.CacheOutput

ASP.NET Web API CacheOutput - library to allow you to cache the output of ApiControllers
Other
883 stars 254 forks source link

Client-cached WebAPI response doesn't update when changing users, using PerUserCacheKeyGenerator #269

Open nomorechickennuggets opened 2 years ago

nomorechickennuggets commented 2 years ago

An example controller:

   [CacheOutput(ServerTimeSpan = 1000, ClientTimeSpan = 1000, CacheKeyGenerator = typeof(PerUserCacheKeyGenerator))]
   public HttpResponseMessage AllUserEntries()

Expected behavior: As a user, I should be able to auth/unauth/change users and experience the smooth UX of client-side cached bits. Technical perspective: when User.Identity (the built-in identity mechanism) changes (from eg unauthenticated to authenticated, or from one user to another), the response from AllUserEntries should change, too. The client-side-cached response should only persist for as long as the current authentication state is maintained.

Actual behavior: I start my app logged in as UserA, app fetches AllUserEntries, I log out, and UserA's data is still persisted on the client - AllUserEntries isn't executed again because the browser believes it has what it needs. So if someone opened my app at the public library, and then logged out, other users would still see UserA's cached, private artifacts.

Questions:

  1. How do I ensure that PerUserCacheKeyGenerator impacts response headers to ensure expected behavior? (Would love an "easy button" but maybe somehow telling the client to compare the AUTH cookie to that stashed in the cached response would be a good way to say "hey client it's time to ask the server, discard those bits").

  2. Would it be possible to do this in such a way where manually invalidating the cache on the server also invalidates it for clients? Eg in many places I use cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey((EntryApiController t) => t.AllUserEntries())); which works well for server-side-cache invalidation. Would love for this to magically invalidate client-side cache somehow...

  3. I'm considering just appending the current user's identity + cache-busting timestamp as URI params to every request that uses client-side caching - something like GET /allUserEntries?username=foo&cacheLastUpdated=20220321929291 - and then the server can "push" a new timestamp whenever the user's cached data needs to be updated. Thoughts on this pattern? Haven't thought through security/privacy concerns here - eg after signing off, maybe my cached data could still be "inspected" or otherwise captured by an adversary.

cc @dmalanij as I believe you're thinking about this - but no pressure / no expectations on my end 🙏