aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/auth.rs')
-rw-r--r--src/api/auth.rs18
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,