Skip to main content

better_auth_core/utils/
cookie_utils.rs

1//! Shared cookie utilities for building `Set-Cookie` headers.
2//!
3//! This module centralises the session cookie construction that was previously
4//! duplicated across every plugin (`email_password`, `passkey`, `two_factor`,
5//! `admin`, `password_management`, `session_management`, `email_verification`).
6
7use crate::config::AuthConfig;
8use cookie::{Cookie, SameSite as CookieSameSite};
9
10/// Build a `Set-Cookie` header value for a session token using the `cookie`
11/// crate for correct formatting and escaping.
12pub fn create_session_cookie(token: &str, config: &AuthConfig) -> String {
13    let session_config = &config.session;
14
15    let expires_offset = cookie::time::OffsetDateTime::now_utc()
16        + cookie::time::Duration::seconds(session_config.expires_in.num_seconds());
17
18    let same_site = map_same_site(&session_config.cookie_same_site);
19
20    let mut cookie = Cookie::build((&*session_config.cookie_name, token))
21        .path("/")
22        .expires(expires_offset)
23        .secure(session_config.cookie_secure)
24        .http_only(session_config.cookie_http_only)
25        .same_site(same_site);
26
27    // SameSite=None requires the Secure attribute per the spec
28    if matches!(
29        session_config.cookie_same_site,
30        crate::config::SameSite::None
31    ) {
32        cookie = cookie.secure(true);
33    }
34
35    cookie.build().to_string()
36}
37
38/// Build a `Set-Cookie` header value that clears the session cookie.
39pub fn create_clear_session_cookie(config: &AuthConfig) -> String {
40    let session_config = &config.session;
41
42    let same_site = map_same_site(&session_config.cookie_same_site);
43
44    let mut cookie = Cookie::build((&*session_config.cookie_name, ""))
45        .path("/")
46        .expires(cookie::time::OffsetDateTime::UNIX_EPOCH)
47        .secure(session_config.cookie_secure)
48        .http_only(session_config.cookie_http_only)
49        .same_site(same_site);
50
51    if matches!(
52        session_config.cookie_same_site,
53        crate::config::SameSite::None
54    ) {
55        cookie = cookie.secure(true);
56    }
57
58    cookie.build().to_string()
59}
60
61fn map_same_site(s: &crate::config::SameSite) -> CookieSameSite {
62    match s {
63        crate::config::SameSite::Strict => CookieSameSite::Strict,
64        crate::config::SameSite::Lax => CookieSameSite::Lax,
65        crate::config::SameSite::None => CookieSameSite::None,
66    }
67}