From c9cc9bc0cb03ce6471804f0e66967d94978898ee Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 9 Nov 2026 11:59:44 +0000 Subject: dashboard: going to another node's dashboard without its login page in between Going to another member's dashboard showed its login page for a moment: a browser without a session there was sent from `/admin/dashboard` to `/login` (by `auth::basic_auth`), which began a session with the token handed over and went on to the dashboard. Now the dashboard's page is served without authentication, as the login page is (it holds nothing: what it shows it reads with the browser's session). Opened with a token handed over, the page begins the session with it (`POST /auth/session`) before it reads anything; without a session, `obtainTokens` goes to the login page, as the redirect did. A request without credentials is refused at once rather than after the 1.5 s that slow down guessing passwords: nothing is guessed there, and a page without a session goes to the login page without waiting twice for it. --- src/api/auth.rs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'src/api/auth.rs') diff --git a/src/api/auth.rs b/src/api/auth.rs index abb8c1a..fb03ea1 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -308,21 +308,10 @@ pub(crate) async fn basic_auth( .map(|user| (user, Via("htpasswd"))), }; let Some((user, via)) = user else { - sleep(Duration::from_millis(1500)).await; - // A browser opening the dashboard: to the page to log in on. - if cfg!(feature = "dashboard") - && request.method() == axum::http::Method::GET - && request.uri().path() == "/admin/dashboard" - && headers - .get(axum::http::header::ACCEPT) - .and_then(|accept| accept.to_str().ok()) - .is_some_and(|accept| accept.contains("text/html")) - { - return ( - StatusCode::SEE_OTHER, - [(axum::http::header::LOCATION, "../login")], - ) - .into_response(); + // Slowing down guessing: only where credentials came (none: nothing guessed, and + // a page without a session goes to the login page at once). + if headers.contains_key(AUTHORIZATION) { + sleep(Duration::from_millis(1500)).await; } // 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 -- cgit v1.3.1