Dashboard 2.0 PWA: Service Worker prevents authentication redirect when session expires

I'm running Node-RED with Dashboard 2.0 behind Cloudflare Access (Zero Trust), which handles authentication. The dashboard is accessed via a public URL that tunnels back to my home network. I've installed the dashboard as a PWA on my iPhone (Add to Home Screen), so it opens in its own standalone window.

The Cloudflare Access session expires after a set amount of time. When this happens and I open the PWA, I expect to be redirected to the Cloudflare login page so I can re-authenticate. Instead, I see "There was an error loading the Dashboard" with the disconnected image and a "Reload App" button. Reloading does not help, it shows the same error every time.
The only way I've found to recover is to delete the PWA from my home screen and re-add it.
What's happening under the hood:
I captured HAR files from the failing sessions and the root cause seems to be that the Service Worker that Dashboard 2.0 registers caches everything, including index.html and the main JS bundle. When I open the PWA:

  1. The Service Worker intercepts the navigation request and serves index.html from its cache (status 200, _fetchType: "Service Worker")
  2. The cached JavaScript boots the Vue app and calls fetch("_setup")
  3. The _setup request goes to the network, but Cloudflare Access blocks it (session expired) and the cross-origin redirect causes the fetch to fail
  4. The catch handler shows "There was an error loading the Dashboard"
  5. No request ever reaches the network, so Cloudflare never gets a chance to redirect to its login page

Has anyone else run into this? Is there a configuration option I'm missing, or would this need a change in how the dashboard's Service Worker is configured?

Hi,

We've seen similar issues with the service worker and I have spent hours trying to figure out how to fix it. In the end, the only reliable fix I could find was to disable the service worker entirely (which you can do in the dashboard base config node).

The problem comes down to the service working making http requests to revalidate its manifest - and those requests failing auth. I could not find anyway to programmatically react to those failing requests.This must be a common problem with service workers, but I couldn't find any useful tips on how to resolve it.

1 Like

On Android, refreshing the page sends it to the login page.

Oh, sorry, I see that I have disabled Install as App.

Something must receive the 301 redirect - is that in Node-RED or in the web worker?

Surely there must be a way to detect getting a 301 instead of a valid response?

That is what I assume, and what I have spent a lot of time trying to figure out. It's buried in the web worker - and the various frameworks layered on top. I couldn't find a straight answer for it.

.... and don't call me Shirely ....

Ah, is the web worker something that has been generated? Sorry, I've not looked at the WW in D2.

I'm curious to know, where is that setting? Is that Allow App Installation, because I can't seem to find anything that says disable service worker. I really don't want to disable Allow App Installation.

I might take a stab at the service worker myself, but if you've already spent hours then I'm not sure I would be much more successful.

Never mind, I can see that it uses Workbox.

So Workbox does expose fetchDidSucceed and fetchDidFail on routes.

So you need some kind of auth plugin for workbox - Claude suggested a possible solution that might be worth looking at?

https://claude.ai/share/c7d7d3b2-ca9d-4d9f-94f4-a036156e1c99

I'm trying this change now, and with 15 minute session length in Cloudflare, I haven't reproduce the issue yet.

I admit this change was done with the help of Opus 4.6, and I don't exactly know if there's any major downsides of this.

1 Like