Set 'SameSite' to 'Lax' on removal cookies.

This avoids needless warnings from certain browsers.
This commit is contained in:
Sergio Benitez 2023-11-01 12:08:26 -05:00
parent 48d1b82e84
commit fa0c778276
1 changed files with 56 additions and 19 deletions

View File

@ -350,17 +350,24 @@ impl<'a> CookieJar<'a> {
self.ops.lock().push(Op::Add(cookie, true)); self.ops.lock().push(Op::Add(cookie, true));
} }
/// Removes `cookie` from this collection and generates a "removal" cookies /// Removes `cookie` from this collection and generates a "removal" cookie
/// to send to the client on response. A "removal" cookie is a cookie that /// to send to the client on response. A "removal" cookie is a cookie that
/// has the same name as the original cookie but has an empty value, a /// has the same name as the original cookie but has an empty value, a
/// max-age of 0, and an expiration date far in the past. /// max-age of 0, and an expiration date far in the past.
/// ///
/// **Note: For correctness, `cookie` must contain the same `path` and /// **For successful removal, `cookie` must contain the same `path` and
/// `domain` as the cookie that was initially set. Failure to provide the /// `domain` as the cookie that was originally set. The cookie will fail to
/// initial `path` and `domain` will result in cookies that are not properly /// be deleted if any other `path` and `domain` are provided. For
/// removed. For convenience, if a path is not set on `cookie`, the `"/"` /// convenience, a path of `"/"` is automatically set when one is not
/// path will automatically be set.** /// specified.** The full list of defaults when corresponding values aren't
/// specified is:
/// ///
/// * `path`: `"/"`
/// * `SameSite`: `Lax`
///
/// <small>Note: a default setting of `Lax` for `SameSite` carries no
/// security implications: the removal cookie has expired, so it is never
/// transferred to any origin.</small>
/// ///
/// # Example /// # Example
/// ///
@ -370,47 +377,62 @@ impl<'a> CookieJar<'a> {
/// ///
/// #[get("/")] /// #[get("/")]
/// fn handler(jar: &CookieJar<'_>) { /// fn handler(jar: &CookieJar<'_>) {
/// // Rocket will set `path` to `/`. /// // `path` and `SameSite` are set to defaults (`/` and `Lax`)
/// jar.remove("name"); /// jar.remove("name");
/// ///
/// // Use a custom-built cookie to set a custom path. /// // Use a custom-built cookie to set a custom path.
/// jar.remove(Cookie::build("name").path("/login")); /// jar.remove(Cookie::build("name").path("/login"));
///
/// // Use a custom-built cookie to set a custom path and domain.
/// jar.remove(Cookie::build("id").path("/guide").domain("rocket.rs"));
/// } /// }
/// ``` /// ```
pub fn remove<C: Into<Cookie<'static>>>(&self, cookie: C) { pub fn remove<C: Into<Cookie<'static>>>(&self, cookie: C) {
let mut cookie = cookie.into(); let mut cookie = cookie.into();
if cookie.path().is_none() { Self::set_removal_defaults(&mut cookie);
cookie.set_path("/");
}
self.ops.lock().push(Op::Remove(cookie, false)); self.ops.lock().push(Op::Remove(cookie, false));
} }
/// Removes the private `cookie` from the collection. /// Removes the private `cookie` from the collection.
/// ///
/// For correct removal, the passed in `cookie` must contain the same `path` /// **For successful removal, `cookie` must contain the same `path` and
/// and `domain` as the cookie that was initially set. If a path is not set /// `domain` as the cookie that was originally set. The cookie will fail to
/// on `cookie`, the `"/"` path will automatically be set. /// be deleted if any other `path` and `domain` are provided. For
/// convenience, a path of `"/"` is automatically set when one is not
/// specified.** The full list of defaults when corresponding values aren't
/// specified is:
///
/// * `path`: `"/"`
/// * `SameSite`: `Lax`
///
/// <small>Note: a default setting of `Lax` for `SameSite` carries no
/// security implications: the removal cookie has expired, so it is never
/// transferred to any origin.</small>
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// # #[macro_use] extern crate rocket; /// # #[macro_use] extern crate rocket;
/// use rocket::http::CookieJar; /// use rocket::http::{CookieJar, Cookie};
/// ///
/// #[get("/")] /// #[get("/")]
/// fn handler(jar: &CookieJar<'_>) { /// fn handler(jar: &CookieJar<'_>) {
/// // `path` and `SameSite` are set to defaults (`/` and `Lax`)
/// jar.remove_private("name"); /// jar.remove_private("name");
///
/// // Use a custom-built cookie to set a custom path.
/// jar.remove_private(Cookie::build("name").path("/login"));
///
/// // Use a custom-built cookie to set a custom path and domain.
/// let cookie = Cookie::build("id").path("/guide").domain("rocket.rs");
/// jar.remove_private(cookie);
/// } /// }
/// ``` /// ```
#[cfg(feature = "secrets")] #[cfg(feature = "secrets")]
#[cfg_attr(nightly, doc(cfg(feature = "secrets")))] #[cfg_attr(nightly, doc(cfg(feature = "secrets")))]
pub fn remove_private<C: Into<Cookie<'static>>>(&self, cookie: C) { pub fn remove_private<C: Into<Cookie<'static>>>(&self, cookie: C) {
let mut cookie = cookie.into(); let mut cookie = cookie.into();
if cookie.path().is_none() { Self::set_removal_defaults(&mut cookie);
cookie.set_path("/");
}
self.ops.lock().push(Op::Remove(cookie, true)); self.ops.lock().push(Op::Remove(cookie, true));
} }
@ -508,6 +530,21 @@ impl<'a> CookieJar<'a> {
} }
} }
/// For each property below, this method checks if there is a provided value
/// and if there is none, sets a default value. Default values are:
///
/// * `path`: `"/"`
/// * `SameSite`: `Lax`
fn set_removal_defaults(cookie: &mut Cookie<'static>) {
if cookie.path().is_none() {
cookie.set_path("/");
}
if cookie.same_site().is_none() {
cookie.set_same_site(SameSite::Lax);
}
}
/// For each property mentioned below, this method checks if there is a /// For each property mentioned below, this method checks if there is a
/// provided value and if there is none, sets a default value. Default /// provided value and if there is none, sets a default value. Default
/// values are: /// values are: