proxy auth broken again
My website is broken again using proxy auth on subdomain.
All i get is a permanent page reload and no browser authentication popup from silberbullet
I have just upgraded from ad old, but working, build to latest release on github.
Its a regression, sorry ;)
Previously it was this ticket: https://github.com/silverbulletmd/silverbullet/issues/804
And it was fixed.
Some more context:
- I host sb on "notes.mydomain.net"
- I have a nginx reverse proxy that redirect and authenticate, to sb socket
- sb runs on my server as its dedicated user for proper filesystem permissions
- sb downloaded from github releases page
- Firefox just reload the page indefinitely if not already authenticated
- before, after issue 804 was fixed, it would popup a browser authentication dialog and then would work
Currently I am forced to stop using sb at least while outside home, where the proxy auth is not used.
Do you happen to remember what the mat version was that you ran? And now you're on 0.9? I don't think anything has changed here for a very long time.
I am currently using 0.9.0, and i was previously on 0.7.6 (IIRC).
I have to say that the issue seems to be present only on mobile browsers (tested latest Firefox on Android). Both Chrome and Firefox on Linux instead do a single page reload and then the auth popup is displayed.
Same issue on MacOS & iOS using Safari or in PWA. Also Firefox on MacOS shows the issue.
I was able to interrupt the endless reload loop and capture some information from the browser's console. Hope that helps.
Got error fetching, throwing offline "<url>/index.json" - TypeError: Load Failed - client.js:18:16709
Error: Offline - client.js:17
Booting SilverBullet client - "in Online Mode"
Service worker registered...
Rebuilding editor state
Failed to load resource: the server responded with a status of 401 - <url>/.ping
Failed to load resource: the server responded with a status of 503 - <url>/index.json
Could not reach remote server, we're offline or the server is down - Error: Not authenticated, got 403 - client.js:18:16563
Loading plugs
(Re)loading plugs
alreadyFetching is on, skipping even triggering for fetchFileList - client.js:18
Error: Offline - client.js:18
Failed to load resource: the server responded with a status of 503 - <url>/index.json
Error: Offline - client.js:18
...
I am running 0.9.0 as well.
Ok, pushed some tweaks to default, should be on edge soon. Could you check if this fixes or at least gives some more info?
I have just tried build 0.9.2 and i can report that now not even Firefox on linux works, the page just keep reloading forever. what's annoying is that i can see the entire content of the page even before the authentication (but this might be cached in the browser).
I need to test edge but unclear how to do it
The website now keeps popping up "You are not authenticated, going to reload and hope that that kicks off authentication" forever. Tried on Chrome and Firefox for Linux.
This is from firefox javascript console while stopped at popup:
Loading plugs [client.js:2528:21166](https://notes.mydomain.com/.client/client.js)
(Re)loading plugs [client.js:2528:21225](https://notes.mydomain.com/.client/client.js)
Activated plug editor [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug emoji [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug federation [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug index [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug markdown [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Booting up worker for markdown [client.js:2247:17012](https://notes.mydomain.com/.client/client.js)
Activated plug plug-manager [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug query [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug search [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug share [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug sync [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug tasks [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
Activated plug template [client.js:2247:22110](https://notes.mydomain.com/.client/client.js)
GET
https://notes.mydomain.com/_plug/markdown.plug.js
NS_ERROR_CORRUPTED_CONTENT
Booting SilverBullet client in Sync Mode [client.js:2547:1577](https://notes.mydomain.com/.client/client.js)
Service worker registered... [client.js:2547:1985](https://notes.mydomain.com/.client/client.js)
Index plug not loaded yet, falling back to default config [client.js:2544:366](https://notes.mydomain.com/.client/client.js)
Rebuilding editor state [client.js:2545:5610](https://notes.mydomain.com/.client/client.js)
XHRGET
https://notes.mydomain.com/.ping
[HTTP/1.1 401 Unauthorized 0ms]
Errore nella mappatura delle origini: Error: request failed with status 401
URL risorsa: https://notes.mydomain.com/.client/client.js
URL mappa delle origini: client.js.map
This is all i get in my NGINX logs (error log is empty) when i click on the popup button:
127.0.0.1 - - [26/Aug/2024:14:25:37 +0200] "GET /.ping HTTP/1.1" 401 375 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" "-"
127.0.0.1 - - [26/Aug/2024:14:25:37 +0200] "GET /.client/client.js.map HTTP/1.1" 401 375 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" "-"
127.0.0.1 - - [26/Aug/2024:14:25:37 +0200] "GET /service_worker.js HTTP/1.1" 401 375 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" "-"
to complete the picture, here is my NGINX configuration for Silverbullet:
server {
server_name notes.mydomain.com;
listen 443 ssl;
auth_pam "MyAuth";
auth_pam_service_name "myPamServiceName";
location / {
client_max_body_size 512M;
proxy_pass http://127.0.0.1:8001$uri;
}
}
(only relevant parts, some lines omitted like Let's Encrypt lines and such)
(edit: edited to reflect new discoveries)
The question is: what should SilverBullet do when it starts to get 401s? The assumption is a redirect is in place to send the user to a login page, but if that's not there... what should it do?
I have no idea, usually any web page i use that require a login does get the login, when using the Proxy Auth, the browser automatically pops up the login form before even showing anything. For some reason, which i don't know, when the web page contains Silverbuller there is no login popup., whatever SB is doing, is preventing the browser from showing that popup.
Does Silverbullet support any kind of auth otherwise? I need auth because i host on a public subdomain, but i don't need to use Proxy Auth is there is another option.
https://silverbullet.md/Authentication
Ok, better than being unable to use it, but still I hope the proxy auth can be fixed!
Does Silverbullet support any kind of auth otherwise? I need auth because i host on a public subdomain, but i don't need to use Proxy Auth is there is another option.
I'm setting up Silverbullet behind Cloudflare Access. It's easy to setup, and works as expected most of the time right now.
Sorry, not using cloudflare at all, and there is no reason to. Proxy Auth works fine for all services, except SB at the moment.
Would be possible to totally disable any managing of auth or 401 errors within SB and see if that fix it? Maybe with a command line option?
I think something is really broken with SB authentication. I have done some more experimenting trying to connect SB with my authelia instance.
If i login with authelia, then open the SB subdomain, SB will work just fine.
If i logout from authelia then try to open SB subdomain, the expected behaviour is that the browser opens the authelia login page ( login.mydomain.com) which, in turn, will redirect to SB subdomain (notes.mydomain.com). This is configured in the reverse proxy and just works for the other subdomains i am using it on.
Instead, the SB page will reload indefinitely saying it's offline and cannot access. This is an extract of the firefox console log:
error General sync error: Offline [client.js:18:6946](https://notes.mydomain.com/.client/client.js)
Sync error Offline [client.js:18:13480](https://notes.mydomain.com/.client/client.js)
Errore nella mappatura delle origini: Error: NetworkError when attempting to fetch resource.
URL risorsa: https://notes.mydomain.com/.client/client.js
URL mappa delle origini: client.js.map
Flushed widget cache to store [client.js:2547:1301](https://notes.mydomain.com/.client/client.js)
Syncing file index.md [client.js:18:13742](https://notes.mydomain.com/.client/client.js)
XHRGET
https://notes.mydomain.com/index.md
[HTTP/1.1 503 0ms]
Sync error Error: Offline
authenticatedFetch https://notes.mydomain.com/.client/client.js:18
getFileMeta https://notes.mydomain.com/.client/client.js:18
getFileMeta https://notes.mydomain.com/.client/client.js:18
syncFile https://notes.mydomain.com/.client/client.js:18
init https://notes.mydomain.com/.client/client.js:2544
[client.js:18:14473](https://notes.mydomain.com/.client/client.js)
Syncing file index.md [client.js:18:13742](https://notes.mydomain.com/.client/client.js)
XHRGET
https://notes.mydomain.com/index.md
[HTTP/1.1 503 0ms]
There is also that CORS error (Errore nella mappatura delle origini), which baffles me because there is no reason for it at all to be there, everything is on the same domain.
And the last worrying bit is that i can see the content of the page even if i am not authenticated.
Just pushed some more changes to try to address this. If you could try this on edge again that'd be great.
Had to revert the change. Broke other stuff.
For another stupid web page I have, I just added a JavaScript reload line on any ajax failed promise, and that works, but SB it's much more complex.
Clearing the cache on the client browser fixes this. Following this, forcing a cache clear also fixes this:
http_space_primitives.ts
if (result.status === 401 || result.status === 403) {
alert(
"You are not authenticated, going to reload and try to clear the cache, hopefully that kicks off authentication"
);
try {
const cacheNames = await caches.keys();
await Promise.all(cacheNames.map((name) => caches.delete(name)));
} catch (err) {
console.error("Failed to clear cache:", err);
}
location.reload();
throw new Error("Not authenticated, got 401");
}
But I have no idea if this is an appropriate thing to do here, or would have downstream consequences. Hope this helps though.
Right, I was thinking of solving it similarly not with caches but by unregistering the service worker when an auth problem happens. Doing that and reloading should also solve this issue.
FWIW, also an issue with a Caddy-based authenticated proxy.
I'm using shared auth across a couple of services on a few different subdomains, and can work around it by visiting one of the other services (e.g. sonarr). Not sure why SB in particular is having trouble, but-
(headers) {
header Strict-Transport-Security "max-age=31536000; includeSubdomains"
header X-Clacks-Overhead "GNU Terry Pratchett"
header X-Frame-Options "allow-from https://madoka.brage.info"
header X-XSS-Protection "1; mode=block"
header Referrer-Policy "no-referrer-when-downgrade"
encode zstd gzip
handle_errors {
header content-type "text/plain"
respond "{http.error.status_code} {http.error.status_text}"
}
}
(password) {
forward_auth localhost:9091 {
uri /api/verify?rd=https://auth.brage.info/
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
todo.brage.info {
import headers
import password
reverse_proxy http://localhost:3000
}
The relevant parts of the config. Which should be fine; it's basically right out of the manual. This would be returning (IIRC) a 302 if reauthentication needs to happen...
Does the web worker handle 302s correctly? It can't just fire off another fetch; it needs to reload the entire page with the generated auth url.
The question is: what should SilverBullet do when it starts to get 401s? The assumption is a redirect is in place to send the user to a login page, but if that's not there... what should it do?
I have a suggestion.
I haven't looked at the implementation, so I don't know whether or not it will work.
In particular, I don't know what problem reloading was originally trying to solve, so I might be missing a key point.
I think there are two broad cases:
- Silverbullet itself requires authentication; or
- a reverse proxy in front of Silverbullet requires authentication.
You should be able to tell the two cases apart, no?
In the first case the error should be coming from Silverbullet's own server; in the second case it isn't.
If the error is coming from Silverbullet's own server, put up the login form and wait for the user to log in.
If the error isn't coming from Silverbullet's own server, put up a message (e.g. "401 Unauthorized"), and poll the Silverbullet server until access is granted.
Just popping in to say I have the same issue with Caddy instead of Nginx. I didn't think it was related to silverbullet at all since I use the authentification from Caddy and not from silverbullet, but this issue is the first link I got when I googled the issue. Clearing site data fixed the issue.
TL;DR: experienced the same issue - "infinite auth loop" - with basic auth on my nginx proxy, accessing SB through Firefox on Android.
Able to work around it by disabling basic auth.
Issue never observed in Firefox on Ubuntu, nor in Chrome on Android.
FWIW same observation here - infinite auth loop on Android Firefox, fixed by clearing "Cookies and site data".
Issue not seen in Ubuntu Firefox.
Running SB 2.0.0-pre4-18-g03507767 on subdomain behind Nginx, only using SB auth.
EDIT: doesn't seem to happen in Android Chrome browser.
Not sure if it matters but also: I just realised I have basic auth enabled in nginx as well - so using both basic auth in nginx as well as SB auth.
EDIT 2: As @gardiol also observed, I get 401s in my nginx log, but no log output from silverbullet itself so it's unclear if the requests even hit silverbullet.
So far, disabling basic auth in the nginx config seems to fix the issue for me, so I'll use this setup for the next few days and report back.
Possibly related: Basic‑Auth Login dialog suppressed when a Service Worker fetches a protected resource
https://bugzilla.mozilla.org/show_bug.cgi?id=1963291
I have exactly this issue using Caddy and oauth2-proxy.. removing cached stuff for the site does appear to fix it, however that can be quite painful especially on mobile. I don't really understand what the problem is.
I'm curious to see if anybody has found a workaround? I have silverbullet behind Authentik with proxy, but I cannot use it on the phone browser or even PWA because it always says "Could not process config and no cached copy, please connect to the internet"
It seems to try to load a cached copy of Authentik.
What status code is it returning? Can you see?
There is no error code, it seems to be a CORS error in my case:
Access to fetch at 'https://authentik.domain.com/application/o/authorize/?client_id=PowzYM5b5szWVqShNOl5MON116duvHSLPI24w4fO&redirect_uri=https%3A%2F%2Fsilverbullet.domain.com%2Foutpost.goauthentik.io%2Fcallback%3FX-authentik-auth-callback%3Dtrue&response_type=code&scope=ak_proxy+openid+profile+entitlements+email&state=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnb2F1dGhlbnRpay5pby9vdXRwb3N0L1Bvd3pZTTViNXN6V1ZxsdfT2w1TU9OMTE2ZHV2SFNMUEkyNHc0Zk8iLCJzaWQiOiJLU05IUlNEUawdekRIWVpQVk9LVzZBNkQzUjNMNFZaTE9aTURKQk03S1hOTFc0UUhPUkRRIiwic3RhdGUiOiJnT1pzRl9UejZuenRtLXI0dVhxVGpTaXFOVVBKemp4allZVFo4TlE1RDIwIiwicmVkaXJlY3QiOiJodHRwczovL3NpbHZlcmJ1bGxldC5rdWJlLjRzaC5pby8uY2xpZW50L2NsaWVudC5qcz92PWNhY2hlLTE3NjEwNDY5NTU3NDcifQ.X6pY5WlBMP2_OJjNE1MjxvVaKA8c-Zv7ZWmkvtYSWX8' (redirected from 'https://silverbullet.domain.com/.client/client.js?v=cache-1761046955747') from origin 'https://silverbullet.domain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Which only happens with a cached version.