From 9fdb4ac727fbf36f103c9ea35cfaa6d3aedb398b Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Thu, 7 Aug 2025 10:23:06 +0200 Subject: [PATCH] fix(web): set secure cookie flag only for https (#4345) --- .../src/web_client/authentication.rs | 36 +++++++++++++------ zellij-client/src/web_client/http_handlers.rs | 10 ++++-- zellij-client/src/web_client/mod.rs | 2 ++ zellij-client/src/web_client/types.rs | 1 + 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/zellij-client/src/web_client/authentication.rs b/zellij-client/src/web_client/authentication.rs index ed15f6d6..0327a095 100644 --- a/zellij-client/src/web_client/authentication.rs +++ b/zellij-client/src/web_client/authentication.rs @@ -20,22 +20,36 @@ pub async fn auth_middleware(request: Request, next: Next) -> Result { // revoke session_token as if it exists it's no longer valid - let clear_cookie = Cookie::build(("session_token", "")) - .http_only(true) - .secure(true) - .same_site(SameSite::Strict) - .path("/") - .max_age(time::Duration::seconds(0)) - .build(); - let mut response = Response::builder() .status(StatusCode::UNAUTHORIZED) .body(Body::empty()) .unwrap(); - response - .headers_mut() - .insert(SET_COOKIE, clear_cookie.to_string().parse().unwrap()); + // Clear both secure and non-secure versions + // in case the user was on http before and is now on https + // or vice versa + let clear_cookies = [ + Cookie::build(("session_token", "")) + .http_only(true) + .secure(false) + .same_site(SameSite::Strict) + .path("/") + .max_age(time::Duration::seconds(0)) + .build(), + Cookie::build(("session_token", "")) + .http_only(true) + .secure(true) + .same_site(SameSite::Strict) + .path("/") + .max_age(time::Duration::seconds(0)) + .build(), + ]; + + for cookie in clear_cookies { + response + .headers_mut() + .append(SET_COOKIE, cookie.to_string().parse().unwrap()); + } Ok(response) }, diff --git a/zellij-client/src/web_client/http_handlers.rs b/zellij-client/src/web_client/http_handlers.rs index df684b60..20c946b5 100644 --- a/zellij-client/src/web_client/http_handlers.rs +++ b/zellij-client/src/web_client/http_handlers.rs @@ -27,17 +27,21 @@ pub async fn serve_html(request: Request) -> Html { html } -pub async fn login_handler(Json(login_request): Json) -> impl IntoResponse { +pub async fn login_handler( + State(state): State, + Json(login_request): Json, +) -> impl IntoResponse { match create_session_token( &login_request.auth_token, login_request.remember_me.unwrap_or(false), ) { Ok(session_token) => { + let is_https = state.is_https; let cookie = if login_request.remember_me.unwrap_or(false) { // Persistent cookie for remember_me Cookie::build(("session_token", session_token)) .http_only(true) - .secure(true) + .secure(is_https) .same_site(SameSite::Strict) .path("/") .max_age(time::Duration::weeks(4)) @@ -46,7 +50,7 @@ pub async fn login_handler(Json(login_request): Json) -> impl Into // Session cookie - NO max_age means it expires when browser closes/refreshes Cookie::build(("session_token", session_token)) .http_only(true) - .secure(true) + .secure(is_https) .same_site(SameSite::Strict) .path("/") .build() diff --git a/zellij-client/src/web_client/mod.rs b/zellij-client/src/web_client/mod.rs index a6fe4765..33776695 100644 --- a/zellij-client/src/web_client/mod.rs +++ b/zellij-client/src/web_client/mod.rs @@ -229,6 +229,7 @@ pub async fn serve_web_client( } }); + let is_https = rustls_config.is_some(); let state = AppState { connection_table: connection_table.clone(), config: Arc::new(Mutex::new(config)), @@ -236,6 +237,7 @@ pub async fn serve_web_client( config_file_path, session_manager, client_os_api_factory, + is_https, }; tokio::spawn({ diff --git a/zellij-client/src/web_client/types.rs b/zellij-client/src/web_client/types.rs index 901923c8..c751199b 100644 --- a/zellij-client/src/web_client/types.rs +++ b/zellij-client/src/web_client/types.rs @@ -174,6 +174,7 @@ pub struct AppState { pub config_file_path: PathBuf, pub session_manager: Arc, pub client_os_api_factory: Arc, + pub is_https: bool, } #[derive(Debug, Clone, Serialize, Deserialize)]