use super::*;
#[derive(Clone)]
#[expect(
clippy::struct_excessive_bools,
reason = "Independent configuration switches model distinct upstream behavior, rather than mutually exclusive states"
)]
pub struct SessionConfig {
pub stateless: bool,
pub cookie_refresh_cache: CookieRefreshCache,
pub secondary_storage: Option<Arc<dyn crate::store::CacheAdapter>>,
pub store_in_database: bool,
pub preserve_in_database: bool,
pub additional_fields: indexmap::IndexMap<String, crate::field_policy::FieldConfig>,
pub expires_in: Duration,
pub update_age: Option<Duration>,
pub disable_session_refresh: bool,
pub defer_session_refresh: bool,
pub fresh_age: Option<Duration>,
pub cookie_name: String,
pub cookie_secure: bool,
pub cookie_http_only: bool,
pub cookie_same_site: SameSite,
pub cookie_cache: Option<CookieCacheConfig>,
}
impl std::fmt::Debug for SessionConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SessionConfig")
.field("secondary_storage", &self.secondary_storage.is_some())
.field("store_in_database", &self.store_in_database)
.field("preserve_in_database", &self.preserve_in_database)
.field("expires_in", &self.expires_in)
.finish_non_exhaustive()
}
}
#[derive(Debug, Clone)]
pub struct JwtConfig {
pub expires_in: Duration,
pub algorithm: String,
pub issuer: Option<String>,
pub audience: Option<String>,
}
#[derive(Debug, Clone)]
pub struct CookieCacheConfig {
pub enabled: bool,
pub max_age: f64,
pub strategy: CookieCacheStrategy,
pub version: Option<crate::session::cookie_cache::CookieCacheVersion>,
}
#[derive(Debug, Clone, Copy, Default)]
pub enum CookieRefreshCache {
#[default]
Disabled,
Automatic,
UpdateAge(f64),
}
impl SessionConfig {
#[must_use]
pub fn stateless(mut self) -> Self {
if !self.stateless {
self.cookie_refresh_cache = CookieRefreshCache::Automatic;
}
self.stateless = true;
if self.cookie_cache.is_none() {
self.cookie_cache = Some(CookieCacheConfig {
enabled: true,
strategy: CookieCacheStrategy::Jwe,
max_age: self.expires_in.num_seconds() as f64,
..CookieCacheConfig::default()
});
}
self
}
#[must_use]
pub fn has_server_session_store(&self) -> bool {
!self.stateless
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CookieCacheStrategy {
Compact,
Jwt,
Jwe,
}
impl Default for CookieCacheConfig {
fn default() -> Self {
Self {
enabled: false,
max_age: 300.0,
strategy: CookieCacheStrategy::Compact,
version: None,
}
}
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
stateless: false,
cookie_refresh_cache: CookieRefreshCache::Disabled,
secondary_storage: None,
store_in_database: false,
preserve_in_database: false,
additional_fields: indexmap::IndexMap::default(),
expires_in: Duration::hours(24 * 7), update_age: Some(Duration::hours(24)), disable_session_refresh: false,
defer_session_refresh: false,
fresh_age: Some(Duration::days(1)),
cookie_name: "better-auth.session_token".to_owned(),
cookie_secure: false,
cookie_http_only: true,
cookie_same_site: SameSite::Lax,
cookie_cache: None,
}
}
}
impl Default for JwtConfig {
fn default() -> Self {
Self {
expires_in: Duration::hours(24), algorithm: "HS256".to_owned(),
issuer: None,
audience: None,
}
}
}