rustauth_core/cookies/
session.rs1use crate::error::RustAuthError;
2
3use super::chunked::ChunkedCookieStore;
4use super::config::merge_options;
5use super::parse::parse_cookies;
6use super::signing::sign_cookie_value;
7use super::types::{
8 strip_secure_cookie_prefix, AuthCookie, AuthCookies, Cookie, SessionCookieOptions,
9 DEFAULT_COOKIE_PREFIX, SECURE_COOKIE_PREFIX,
10};
11
12pub fn get_session_cookie(
13 cookie_header: &str,
14 cookie_prefix: Option<&str>,
15 cookie_name: Option<&str>,
16 secure: bool,
17) -> Option<String> {
18 let prefix = cookie_prefix.unwrap_or(DEFAULT_COOKIE_PREFIX);
19 let name = cookie_name.unwrap_or("session_token");
20 let full_name = format!("{prefix}.{name}");
21 let legacy_name = format!("{prefix}-{name}");
22 let cookies = parse_cookies(cookie_header);
23
24 let candidates = if secure {
30 [
31 format!("{SECURE_COOKIE_PREFIX}{full_name}"),
32 format!("{SECURE_COOKIE_PREFIX}{legacy_name}"),
33 ]
34 } else {
35 [full_name, legacy_name]
36 };
37
38 candidates
39 .iter()
40 .find_map(|candidate| cookies.get(candidate))
41 .cloned()
42}
43
44pub fn set_session_cookie(
45 auth_cookies: &AuthCookies,
46 secret: &str,
47 token: &str,
48 options: SessionCookieOptions,
49) -> Result<Vec<Cookie>, RustAuthError> {
50 let mut attributes = merge_options(
51 auth_cookies.session_token.attributes.clone(),
52 options.overrides,
53 );
54 if options.dont_remember {
55 attributes.max_age = None;
56 }
57
58 let mut cookies = vec![Cookie {
59 name: auth_cookies.session_token.name.clone(),
60 value: sign_cookie_value(token, secret)?,
61 attributes,
62 }];
63
64 if options.dont_remember {
65 cookies.push(Cookie {
66 name: auth_cookies.dont_remember_token.name.clone(),
67 value: sign_cookie_value("true", secret)?,
68 attributes: auth_cookies.dont_remember_token.attributes.clone(),
69 });
70 }
71
72 Ok(cookies)
73}
74
75pub fn expire_cookie(cookie: &AuthCookie) -> Cookie {
76 let mut attributes = cookie.attributes.clone();
77 attributes.max_age = Some(0);
78 Cookie {
79 name: cookie.name.clone(),
80 value: String::new(),
81 attributes,
82 }
83}
84
85pub fn delete_session_cookie(
86 auth_cookies: &AuthCookies,
87 cookie_header: &str,
88 skip_dont_remember: bool,
89) -> Vec<Cookie> {
90 let mut expired = vec![
91 expire_cookie(&auth_cookies.session_token),
92 expire_cookie(&auth_cookies.session_data),
93 expire_cookie(&auth_cookies.account_data),
94 ];
95 expired.extend(expire_unprefixed_alias(&auth_cookies.session_token));
99 expired.extend(clean_chunked_cookie(
100 &auth_cookies.session_data,
101 cookie_header,
102 ));
103 expired.extend(clean_chunked_cookie(
104 &auth_cookies.account_data,
105 cookie_header,
106 ));
107 if !skip_dont_remember {
108 expired.push(expire_cookie(&auth_cookies.dont_remember_token));
109 }
110 expired
111}
112
113fn clean_chunked_cookie(cookie: &AuthCookie, cookie_header: &str) -> Vec<Cookie> {
114 ChunkedCookieStore::new(
115 cookie.name.clone(),
116 cookie.attributes.clone(),
117 cookie_header,
118 )
119 .clean()
120}
121
122fn expire_unprefixed_alias(cookie: &AuthCookie) -> Option<Cookie> {
127 let stripped = strip_secure_cookie_prefix(&cookie.name);
128 (stripped != cookie.name).then(|| {
129 let mut expired = expire_cookie(cookie);
130 expired.name = stripped.to_owned();
131 expired
132 })
133}