Fixed the app window opening without its session cookie on macOS

This commit is contained in:
Thorsten Sommer committed 2026-11-01 11:12:02 +01:00
1 parent 3007893843
commit 89304bea84
4 files changed
+17 -10

No files matched your search

@@ -86,7 +86,7 @@ public sealed class AppAccessMiddleware(RequestDelegate next, AppAccessPolicy po
context.Response.Cookies.Append(AppAccessPolicy.SESSION_COOKIE_NAME, token, new CookieOptions
{
HttpOnly = true,
SameSite = SameSiteMode.Strict,
SameSite = SameSiteMode.Lax,
Path = "/",
IsEssential = true
});
@@ -141,7 +141,7 @@ public sealed class AppAccessMiddlewareTests
Assert.That(response.Headers.Location.ToString(), Is.EqualTo("/"));
Assert.That(cookie, Does.StartWith($"{AppAccessPolicy.SESSION_COOKIE_NAME}={UI_TOKEN}"));
Assert.That(cookie, Does.Contain("httponly"));
Assert.That(cookie, Does.Contain("samesite=strict"));
Assert.That(cookie, Does.Contain("samesite=lax"));
Assert.That(cookie, Does.Contain("path=/"));
Assert.That(cookie, Does.Not.Contain("expires"));
});
+12 -4
View File
@@ -25,12 +25,20 @@ const DEV_BOOT_LINK_FILE: &str = "dev-boot-link.txt";
/// Builds the session cookie of the app window.
///
/// The cookie is for the app host alone and lives as long as the window: it has no expiry date,
/// scripts cannot read it, and the window never sends it with a request which another site
/// started. We parse it from text because the `cookie` crate, whose builder would need its
/// and scripts cannot read it. The window never sends it with a request which a page of another
/// site makes, such as a script the page loads or a form it posts.
///
/// The cookie is `Lax`, not `Strict`. Before the window opens the app, it shows a page of Tauri,
/// `tauri://localhost` on macOS, which is another site than the app. WKWebView counts that page
/// as the one which opened the app, and it would withhold a `Strict` cookie. A `Lax` cookie goes
/// along when a whole page of the app opens. Development builds show the page of the Tauri dev
/// server on the app host instead, which hides the difference.
///
/// We parse the cookie from text because the `cookie` crate, whose builder would need its
/// `SameSite` type, is no direct dependency of ours.
pub fn session_cookie() -> Cookie<'static> {
let token = UI_ACCESS_TOKEN.to_hex_text();
Cookie::parse(format!("{SESSION_COOKIE_NAME}={token}; Domain={APP_HOST}; Path=/; HttpOnly; SameSite=Strict"))
Cookie::parse(format!("{SESSION_COOKIE_NAME}={token}; Domain={APP_HOST}; Path=/; HttpOnly; SameSite=Lax"))
.expect("The session cookie consists of fixed attributes and a hexadecimal token, which always parse.")
}
@@ -132,7 +140,7 @@ mod tests {
let cookie = session_cookie();
assert_eq!(cookie.http_only(), Some(true));
assert!(cookie.same_site().is_some_and(|same_site| same_site.is_strict()));
assert!(cookie.same_site().is_some_and(|same_site| same_site.is_lax()));
}
#[test]
+3 -4
View File
@@ -708,10 +708,9 @@ pub async fn change_location_to(url: tauri::Url) {
//
// The window navigates by itself instead of through a script of the page it shows. That page
// comes from Tauri, which is another site than the app, so the app would count as opened by
// another site, and the window would withhold the session cookie. We take the window out of
// the lock first: the cookie and the navigation need the main thread, which may wait for this
// lock meanwhile.
// comes from Tauri, which is another site than the app; app_access::session_cookie explains
// why the session cookie goes along all the same. We take the window out of the lock first:
// the cookie and the navigation need the main thread, which may wait for this lock meanwhile.
//
// Handing over the cookie waits for the main thread. This function serves a request of the
// runtime API, so the waiting happens outside the async runtime, see runtime/AGENTS.md.