From b99e7ddf38233120ea19485968c12c5548e7fa61 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 7 Nov 2026 22:35:22 +0100 Subject: auth: a login page and browser sessions GET /login without authentication: log in by password or with a token (from a login by key). POST/DELETE /auth/session keep the token as an HttpOnly, SameSite=Strict cookie; the dashboard sends a browser without a user there and renews the session while open. Auth plan M2/M3 (browsers). --- src/api/auth.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/api/auth.rs') diff --git a/src/api/auth.rs b/src/api/auth.rs index 69c7ddb..f28aa22 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -301,6 +301,21 @@ pub(crate) async fn basic_auth( }; 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(); + } // A challenge only where basic authentication can answer it. return match state.users { Some(_) => ( -- cgit v1.3.1