fix(web): set secure cookie flag only for https (#4345)

This commit is contained in:
Aram Drevekenin 2025-08-07 10:23:06 +02:00 committed by GitHub
parent a3cfa0316f
commit 9fdb4ac727
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 35 additions and 14 deletions

View file

@ -20,22 +20,36 @@ pub async fn auth_middleware(request: Request, next: Next) -> Result<Response, S
},
Ok(false) | Err(_) => {
// 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)
},

View file

@ -27,17 +27,21 @@ pub async fn serve_html(request: Request) -> Html<String> {
html
}
pub async fn login_handler(Json(login_request): Json<LoginRequest>) -> impl IntoResponse {
pub async fn login_handler(
State(state): State<AppState>,
Json(login_request): Json<LoginRequest>,
) -> 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<LoginRequest>) -> 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()

View file

@ -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({

View file

@ -174,6 +174,7 @@ pub struct AppState {
pub config_file_path: PathBuf,
pub session_manager: Arc<dyn SessionManager>,
pub client_os_api_factory: Arc<dyn ClientOsApiFactory>,
pub is_https: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]