From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 389621FF183 for ; Wed, 17 Dec 2025 08:58:04 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6CA1C20643; Wed, 17 Dec 2025 08:58:51 +0100 (CET) Mime-Version: 1.0 Date: Wed, 17 Dec 2025 08:58:48 +0100 Message-Id: To: "Thomas Lamprecht" X-Mailer: aerc 0.20.0 References: <20251210135035.237546-1-s.sterz@proxmox.com> <48d9670d-32da-4c5e-a4a2-46e15dd93c03@proxmox.com> In-Reply-To: <48d9670d-32da-4c5e-a4a2-46e15dd93c03@proxmox.com> From: "Shannon Sterz" X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1765958319173 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.039 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [lib.rs] URIBL_SBL_A 0.1 Contains URL's A record listed in the Spamhaus SBL blocklist [188.114.96.3] Subject: Re: [yew-devel] [PATCH yew-comp] http wasm client: load csrf token from global Proxmox object X-BeenThere: yew-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Yew framework devel list at Proxmox List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Yew framework devel list at Proxmox Cc: Thomas Lamprecht , Yew framework devel list at Proxmox Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: yew-devel-bounces@lists.proxmox.com Sender: "yew-devel" On Tue Dec 16, 2025 at 5:53 PM CET, Thomas Lamprecht wrote: > Am 10.12.25 um 14:50 schrieb Shannon Sterz: >> previously csrf tokens were only loaded from session storage. this >> could lead to two scenarios: >> >> - the csrf token expired while the newer authentication ticket was >> still valid. >> - when restoring a session, session cookies were restored, but session >> storage seemingly isn't always restored (tested in chromium and ff). >> this lead to no csrf token being loaded here, the >> `unwrap_or_default()` would then return the empty string as a csrf >> token. >> >> both scenarios would lead to a situation where a valid authentication >> cookie was present, but the csrf token was empty or expired. the >> result is that all GET requests would work properly, as we don't check >> csrf tokens there. however, the first non-GET request would lead to a >> logout. >> >> to fix this, we first load the token from the Proxmox object that is >> injected via a script in the index.html for all proxmox products. we >> prefer this token over the one in session storage. >> authentication_from_cookie (that calls the extract_auth_from_cookie >> function), is and should only be called when the page was just loaded. >> so the csrf token in the Proxmox object will always be fresher than the >> one in the session storage. >> >> additionally, if no csrf token can be found, return None to trigger a >> fresh log in. > > Many thanks for this patch, the basic approach checks out AFAICT, some > comment w.r.t. (pre-existing) code structure inline though. > > >> Signed-off-by: Shannon Sterz >> --- >> >> tested this by opening and closing chromium and firefox after logging in >> with active session restore. without this patch an empty csrf token >> would be loaded (and then persisted to session storage). >> >> note, i intentionally did not put this in load_csrf_token() in lib.rs as >> that could break the assumption that it will always return the same >> token last stored with store_csrf_token(). >> >> src/http_client_wasm.rs | 14 ++++++++++++-- >> 1 file changed, 12 insertions(+), 2 deletions(-) >> >> diff --git a/src/http_client_wasm.rs b/src/http_client_wasm.rs >> index 25d0dd2..ae99a99 100644 >> --- a/src/http_client_wasm.rs >> +++ b/src/http_client_wasm.rs >> @@ -3,9 +3,11 @@ use std::pin::Pin; >> use std::rc::Rc; >> use std::sync::Mutex; >> >> +use js_sys::Reflect; >> use percent_encoding::percent_decode_str; >> use serde::Serialize; >> use serde_json::Value; >> +use wasm_bindgen::JsValue; >> >> use proxmox_client::{Error, HttpApiClient, HttpApiResponse, HttpApiResponseStream}; >> use proxmox_login::{Authentication, Login, Ticket, TicketResult}; >> @@ -55,8 +57,16 @@ fn extract_auth_from_cookie(project: &dyn ProjectInfo) -> Option<(String, String >> if key == name { >> let items: Vec<&str> = value.split(':').take(2).collect(); >> if prefixes.contains(&items[0]) { >> - let csrf_token = crate::load_csrf_token().unwrap_or_default(); >> - return Some((value.to_string(), csrf_token)); > > Might be nice to have a comment here, like: > > // prefer the token from the index template's JS object, which is the most > // recent one, fallback to the one from the session storage (possibly outdated) > > That said, I wonder if the function should be split into one to get the ticket and one to > get the CSRF token which then could be called separately in authentication_from_cookie > as this already feels like two different functions to me, it was just slightly hidden > by the csrf extraction being just a short call to another fn previously. > > This doesn't mean you have to put it in the lib's load_csrf_token though, can be a > helper local to this module with a short doc-comment describing the background. sure we can do that, i thought keeping it as one was easier since this is a private helper function. but yeah two helper functions that are called separately is definitively cleaner, will send a v2. thanks! >> + let window = gloo_utils::window(); >> + if let Ok(proxmox) = Reflect::get(&window, &JsValue::from_str("Proxmox")) { >> + if let Ok(token) = >> + Reflect::get(&proxmox, &JsValue::from_str("CSRFPreventionToken")) >> + { >> + return token.as_string().map(|t| (value.to_string(), t)); >> + } >> + } >> + >> + return crate::load_csrf_token().map(|t| (value.to_string(), t)); >> } >> } >> } >> -- >> 2.47.3 _______________________________________________ yew-devel mailing list yew-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel