tower_cookies/
private.rs

1use crate::Cookies;
2use cookie::{Cookie, Key};
3
4/// A cookie jar that provides authenticated encryption for its cookies.
5///
6/// A _private_ child jar signs and encrypts all the cookies added to it and
7/// verifies and decrypts cookies retrieved from it. Any cookies stored in
8/// `PrivateCookies` are simultaneously assured confidentiality, integrity, and
9/// authenticity. In other words, clients cannot discover nor tamper with the
10/// contents of a cookie, nor can they fabricate cookie data.
11pub struct PrivateCookies<'a> {
12    cookies: Cookies,
13    key: &'a Key,
14}
15
16impl<'a> PrivateCookies<'a> {
17    /// Creates an instance of `PrivateCookies` with parent `cookies` and key `key`.
18    /// This method is typically called indirectly via the `private`
19    /// method of [`Cookies`].
20    pub(crate) fn new(cookies: &Cookies, key: &'a Key) -> Self {
21        Self {
22            cookies: cookies.clone(),
23            key,
24        }
25    }
26
27    /// Adds `cookie` to the parent jar. The cookie's value is encrypted with
28    /// authenticated encryption assuring confidentiality, integrity, and
29    /// authenticity.
30    pub fn add(&self, cookie: Cookie<'static>) {
31        let mut inner = self.cookies.inner.lock();
32        inner.changed = true;
33        inner.jar().private_mut(self.key).add(cookie);
34    }
35
36    /// Returns a reference to the `Cookie` inside this jar with the name `name`
37    /// and authenticates and decrypts the cookie's value, returning a `Cookie`
38    /// with the decrypted value. If the cookie cannot be found, or the cookie
39    /// fails to authenticate or decrypt, `None` is returned.
40    pub fn get(&self, name: &str) -> Option<Cookie<'static>> {
41        let mut inner = self.cookies.inner.lock();
42        inner.jar().private(self.key).get(name)
43    }
44
45    /// Removes the `cookie` from the parent jar.
46    pub fn remove(&self, cookie: Cookie<'static>) {
47        self.cookies.remove(cookie);
48    }
49}
50
51#[cfg(all(test, feature = "private"))]
52mod tests {
53    use crate::Cookies;
54    use cookie::{Cookie, Key};
55
56    #[test]
57    fn get_absent() {
58        let key = Key::generate();
59        let cookies = Cookies::new(vec![]);
60        assert_eq!(cookies.private(&key).get("foo"), None);
61    }
62
63    #[test]
64    fn add_get_private() {
65        let key = Key::generate();
66        let cookies = Cookies::new(vec![]);
67        let cookie = Cookie::new("foo", "bar");
68        let private = cookies.private(&key);
69        private.add(cookie.clone());
70        assert_eq!(private.get("foo").unwrap(), cookie);
71    }
72
73    #[test]
74    fn add_private_get_raw() {
75        let key = Key::generate();
76        let cookies = Cookies::new(vec![]);
77        let cookie = Cookie::new("foo", "bar");
78        cookies.private(&key).add(cookie.clone());
79        assert_ne!(cookies.get("foo").unwrap(), cookie);
80    }
81
82    #[test]
83    fn add_raw_get_private() {
84        let key = Key::generate();
85        let cookies = Cookies::new(vec![]);
86        let cookie = Cookie::new("foo", "bar");
87        cookies.add(cookie);
88        assert_eq!(cookies.private(&key).get("foo"), None);
89    }
90
91    #[test]
92    fn messed_keys() {
93        let key1 = Key::generate();
94        let key2 = Key::generate();
95        let cookies = Cookies::new(vec![]);
96        let cookie = Cookie::new("foo", "bar");
97        cookies.private(&key1).add(cookie);
98        assert_eq!(cookies.private(&key2).get("foo"), None);
99    }
100
101    #[test]
102    fn remove() {
103        let key = Key::generate();
104        let cookies = Cookies::new(vec![]);
105        let private = cookies.private(&key);
106        private.add(Cookie::new("foo", "bar"));
107        let cookie = private.get("foo").unwrap();
108        private.remove(cookie);
109        assert!(private.get("foo").is_none());
110    }
111}