diff options
Diffstat (limited to 'src/api/auth.rs')
| -rw-r--r-- | src/api/auth.rs | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/src/api/auth.rs b/src/api/auth.rs index f4806ca..abb8c1a 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -324,15 +324,19 @@ pub(crate) async fn basic_auth( ) .into_response(); } - // A challenge only where basic authentication can answer it, for the API (curl), - // never for what is meant for browsers: the dashboard, nor a page's own requests - // (`Sec-Fetch-Dest: empty`: fetch, EventSource). The browser would ask for a - // password over the page, which has its own login (`/login`), taking the - // passwords of the same file. + // A challenge only where basic authentication can answer it, for the API (curl, + // which sends the password unasked with `-u` anyway), never to a browser: it would + // ask for a password over the page, which has its own login (`/login`), taking + // the passwords of the same file. A browser: the dashboard's paths, any request + // with `Sec-Fetch-*` (every browser for years: pages, downloads, fetch, + // EventSource), or one calling itself `Mozilla/…`, as every browser does. let for_browsers = request.uri().path().starts_with("/admin/dashboard") + || headers.contains_key("sec-fetch-dest") + || headers.contains_key("sec-fetch-mode") || headers - .get("sec-fetch-dest") - .is_some_and(|dest| dest == "empty"); + .get(axum::http::header::USER_AGENT) + .and_then(|agent| agent.to_str().ok()) + .is_some_and(|agent| agent.starts_with("Mozilla/")); return match state.users { Some(_) if !for_browsers => ( StatusCode::UNAUTHORIZED, |
