Skip to content

[Feature] Allow to clear Service Worker cache #24008

Closed as not planned
Closed as not planned

Description

@Sturgelose

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

As a developer, I clear the cookies, data and relevant user information from the browser when the user logs out.
For privacy and security reasons and to avoid keeping relevant data in the browser's cache, I delete all the relevant data of the user from the cookies and localStorage.
However I cannot do the same from the service worker cache.

Expected behavior

I'd like to be able to clear the Service Worker cache whenever a user logs out, to make sure no other user has access to the cache in any way.

This could be added as a function in the Service Worker provider.

What is the motivation / use case for changing the behavior?

A problem is that if a user [bob] does log in with his/her user account after a logout from another user [alice], the cache of the Service Worker might answer with data from alice's requests, having a privacy problem here... The only difference between the requests is the access Token, and is set in the header, which is not taken in account when caching in the service worker. Thus a properly made request while being offline, would be able to answer the data from another user.

Another problem is that a user could access the cache from the browser web tools and check the contents of the cache, even after the user has logged out.

Environment


Angular version: 6.0.2


Browser:
- All

Activity

  1. added
    featureLabel used to distinguish feature request from other issues
    target: patchThis PR is targeted for the next patch release
    area: service-workerIssues related to the @angular/service-worker package
    on May 21, 2018
  2. added this to the Backlog milestone on May 21, 2018
  3. removed
    target: patchThis PR is targeted for the next patch release
    on May 21, 2018
  4. gkalpak commented on May 21, 2018

    @gkalpak
    Member

    In general, I would probably avoid caching sensitive (i.e. non-public) data in persistent storage. There is no way to guarantee security.

    That said, there are several things that need to be taken into account wrt clearing the caches:

    • Clear all caches (even for static, public data) sounds too heavy-handed and will result in a sub-par experience in many scenarios.
    • Clearing specific caches only is more involved and error-prone.
    • Reliably clearing the correct caches would involve keeping track of older versions that the client has used since their login and clear them too.
      (For context: each manifest version uses different cache instances.)
    • The SW has to be able to cope with some caches being "suddenly" wiped out. (It might already be able to cope with that, but it needs to be explcitly verified.)

    In the meantime, CacheStorage seems to be shared between your main page and SW scripts, so might try clearing the caches yourself (all @angular/service-worker caches' names are prefixed with ngsw:).

  5. Sturgelose commented on May 21, 2018

    @Sturgelose
    Author

    I understand, but any website where you request the user to login (which is a vast majority of online web services), handle private date, which is eventually.... sensitive data. All the non-sensitive data are the assets.

    This means that we shouldn't use cache in any website request that is authenticated, which I think that we all agree that this kills the idea of offline usage PWAs and the user of SW for caching...

    What is true is that we do not need to clear all the caches (didn't think about that), but at least we would need to clear caches of authenticated queries. However, as you say, this also makes it harder to implement, as it's much more probable we get errors (thus also why I suggested clearing everything).

    Taking a close look at the cache structure, I can see that the tables are separated by the assetsGroups and dataGroups. Mostly my suggestion would be to be able to clear the data groups (which get expired from time to time if using strategies such as LRU). I guess that there must be a logic from where you can clear expired cache entries without issues that we could reuse somehow. All the rest of entries, belonging to assets, wouldn't be needed to be cleared.

    I'll see if I can find any piece of code showing how to interact from the website with the SW cache and make use of the prefixes (as you suggest), to clear only the relevant ones.

  6. Sturgelose commented on May 21, 2018

    @Sturgelose
    Author

    After a bit more of research seems that service workers expose a delete cache entry method: https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete

    However, this can only be executed from the service worker itself. Thus, we would need something like the following to "speak" between our Angular app and the SW and inform that we want to clear an specific cache: https://stackoverflow.com/a/28513836.

    Seeing this, SW caches work independently to our Angular app and my guess (this should be tested) is that clearing a cache shouldn't affect to the inner logic of an app as both are two independent logics that can speak via messages.

    The other thing is how the inner workings of the app handle this clearing of the SW:

    • User domain: these are seen virtually as plain requests to an API. Therefore, the logic shouldn't see any change, and after clearing the caches the SW would just do a request to the API as the cache is empty.
    • Angular domain (Service Worker Angular service): Not sure what is coded here (I have no idea where in code this is defined), but this thing shouldn't even cache anything from the SW (we would end with just two caches). In case we are saving stuff such as table names and others, we could force a reload (fresh restart) of all this information after clearing the SW cache. Performance shouldn't be a matter as the aim of all this is to clear the cache after the user logging out, not a critical point where UX requires a super fast rection.
  7. josephliccini commented on May 21, 2018

    @josephliccini

    @Sturgelose you don't have to use the @angular/service-worker package to use a service worker. We are using the workbox-sw and workbox-build in our Angular app. It is a bit more work to set up, but you get a lot more control over the worker and the communications between the worker and the app.

    Workbox: https://github.com/GoogleChrome/workbox
    Medium Article on Angular and Workbox: https://medium.com/progressive-web-apps/using-workbox-2-and-angular-5-to-create-a-progressive-web-app-part-1-app-shell-b14f9872384a

    I assume your SPA has a /logout URL, and from there, you could setup some fetch listener to clear out caches, etc. You also can clear caches from the window

    const keys = await window.caches.keys();
    await Promise.all(keys.map(key => caches.delete(key)));

    I am not sure the behavior of @angular/service-worker if you clear caches in such a manner.

    It's worth noting that if your auth is Session Cookie based, then you will have to get creative, because closing the browser will clear session cookie, but not the caches.

    There are a few issues around clearing data in workbox:
    GoogleChrome/workbox#1365

  8. gkalpak commented on May 22, 2018

    @gkalpak
    Member

    any website where you request the user to login [...] handle private date.
    [...]
    This means that we shouldn't use cache in any website request that is authenticated, which I think that we all agree that this kills the idea of offline usage PWAs and the user of SW for caching...

    There is a trade-off between security/privacy and working offline 😁
    There is no way to store sensitive data in a CacheStorage and not make them easily accessible to anyone with physical access to the machine (without the original user manually clearing the caches).

    After a bit more of research seems that service workers expose a delete cache entry method.
    However, this can only be executed from the service worker itself.

    As @josephliccini mentioned (and I also implied in #24008 (comment)), it can be used from the main app directly.

    That said, it might be interesting to expose a service (e.g. SwCaches) that would allow interacting with the caches (although I can't think of any operation other than clear off the top of my head). E.g.:

    interface SwCaches {
      clearAll();
    
      clearAllAssetGroups();
      clearAssetGroup(name: string);
    
      clearAllDataGroups();
      clearDataGroup(name: string);
    }
  9. Sturgelose commented on May 24, 2018

    @Sturgelose
    Author

    Hey, on this I'll be trying with both solutions suggested 😉 :

    • Try with Workbox-sw
    • Try to clear cache manually (and see what happens).

    Will try to report my findings on this later on 😊

    About the security issue around all this, I didn't see it as a problem with another user accessing physically to it! It's mostly that if a user logs out we will still have data in the cache!

    I'd expect that if the user logs out, he logs out completely, leaving no cache filled with data that they generated and that I had kept cached in case he wants to access to it offline. Mostly because if there is cache, the following user will use similar endpoints and requests (only a different auth token) in the API and the cache might return data from the already logged out user.

    Also, as we do not need that data anymore (user logged out), so why do we need to keep this cache in the browser? Mostly the idea of all this is do a bit of garbage collection in the cache after the log out 😉

  10. DaSchTour commented on Jun 13, 2018

    @DaSchTour

    While looking through this I wonder why angular doesn't use workbox. I think it would be the best solution to just create a angular wrapper for workbox and not reimplement things already done in workbox. I could be so easy 🙄

  11. blackblood19 commented on Oct 5, 2018

    @blackblood19

    @Sturgelose Did you try the solutions suggested?
    I tried clearing cache manually, and it is not working as expected.

    const keys = await window.caches.keys();
    await Promise.all(keys.map(key => caches.delete(key)));
    

    I removed the caches after filtering "ngsw:" and "data" substrings in cache keys to make sure that only api calls (dataGroups) caches are removed. And they did get removed. I confirmed by looking at Cache Storage in Application of Developer tools. Also, I confirmed by printing window.caches.keys().
    My two observations after clearing the cache manually are,

    1. Application is still able to retrieve api responses from Service worker in Offline mode.
    2. In Online mode, Service worker is unable to create the "ngsw:xxxdataxxx" caches again, after they are removed once, but still, service worker is able to save the new api responses somewhere, and it is serving these responses in Offline mode.

    My guess is angular service worker uses some other memory in addition to cache storage. I did this testing in a single tab without changing tabs.

    @gkalpak can you please comment on my observations.. If clearing cache storage manually is not working, which solution should I go with? Will angular 7 have any updates for this? Or using workbox-sw instead of angular service workers, the only solution?

  12. gkalpak commented on Oct 6, 2018

    @gkalpak
    Member

    As I mentioned above, this is currently not supported and it is not guaranteed that clearing the caches works (see #24008 (comment)). In fact, I don't think the SW can currently cope very well with caches being deleted while it is still running (and we have recently merged #26042 to mitigate that).

    If you are only interested in clearing the data-group caches, I suggest you clear the cache contents (not delete the caches themselves).

  13. blackblood19 commented on Oct 7, 2018

    @blackblood19

    @gkalpak I tried clearing the cache contents instead of deleting the caches themselves, it is working as expected. Thanks.

  14. 5 remaining items

  15. onderceylan commented on Jun 2, 2021

    @onderceylan

    You might want to do it with handling the promise chain in a better way, in case you'd like to refresh the page immediately after.

    Here's a snippet clearing the cache storage of all data stored by ngsw;

    clearCacheStorage(): Promise<Promise<boolean>[][]> {
      return caches.keys().then(cacheKeys =>
        Promise.all(
          cacheKeys.map(cacheKey => {
            const ngswRegex = /^(ngsw).*/;
            if (ngswRegex.test(cacheKey)) {
              return caches
                .open(cacheKey)
                .then(cache => cache.keys().then(requests => requests.map(req => cache.delete(req))));
            }
          })
        )
      );
    }

    So you can do a page reload after to populate the cache again;

    this.clearCacheStorage().then(() => {
      window.location.reload();
    });
  16. added
    feature: under considerationFeature request for which voting has completed and the request is now under consideration
    on Jun 5, 2021
  17. gabrielstellini commented on Mar 23, 2022

    @gabrielstellini

    For anyone else visiting this issue - cache.keys() can be dangerous.

    See: the official chromium bugreport and the w3c issue.

    (In case the links go down, here's a quick summary):

    Consider the following code:

     function fillCache() {
        caches.open('test').then(function (cache) {
          for (var i = 0; i < 30000; i++) {
            cache.put('https://example.com/probably-crash-' + i, new Response('ok')).then(function() {
              filled.innerText = i;
            })
          }
        });
      }
    
      function readCache() {
        caches.open('test').then(function (cache) {
          cache.keys().then(function(keys) {
            console.log('success')
          }).catch(function (e) {
            alert(e);
          });
        });
      }
    

    When you run readCache, this will fail because chrome limits the maximum memory to 10mb for the result.
    You can bypass this by using cache.match() instead of cache.keys() as seen here:

    caches.open('test').then(function (cache) {
          caches.match('https://example.com/probably-crash-1').then((result) => console.log(result));
    });
    

    This issue will only show up when you are caching thousands of entries in the cache, hence it may not be immediately obvious while testing the above solutions.

    We needed to clear the entire store, so matches didn't really fit our use case. Deleting the entire cache also resulted in some unexpected behaviour from the ngsw (new entries did not result in the recreation of the store).

  18. JeanMeche commented on Aug 29, 2025

    @JeanMeche
    Member

    With #63364 we've announced that the service-worker package in now in maintenance mode and will not receive feature PRs and feature requests.

    The message is also visible here: https://angular.dev/ecosystem/service-workers

  19. angular-automatic-lock-bot commented on Sep 29, 2025

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  20. locked and limited conversation to collaborators on Sep 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: service-workerIssues related to the @angular/service-worker packagefeatureLabel used to distinguish feature request from other issuesfeature: under considerationFeature request for which voting has completed and the request is now under consideration

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions