better_auth_core/
config.rs1use crate::email::EmailProvider;
2use crate::error::AuthError;
3use chrono::Duration;
4use std::sync::Arc;
5
6#[derive(Clone)]
8pub struct AuthConfig {
9 pub secret: String,
11
12 pub base_url: String,
14
15 pub session: SessionConfig,
17
18 pub jwt: JwtConfig,
20
21 pub password: PasswordConfig,
23
24 pub email_provider: Option<Arc<dyn EmailProvider>>,
26}
27
28#[derive(Debug, Clone)]
30pub struct SessionConfig {
31 pub expires_in: Duration,
33
34 pub update_age: bool,
36
37 pub cookie_name: String,
39
40 pub cookie_secure: bool,
42 pub cookie_http_only: bool,
43 pub cookie_same_site: SameSite,
44}
45
46#[derive(Debug, Clone)]
48pub struct JwtConfig {
49 pub expires_in: Duration,
51
52 pub algorithm: String,
54
55 pub issuer: Option<String>,
57
58 pub audience: Option<String>,
60}
61
62#[derive(Debug, Clone)]
64pub struct PasswordConfig {
65 pub min_length: usize,
67
68 pub require_uppercase: bool,
70
71 pub require_lowercase: bool,
73
74 pub require_numbers: bool,
76
77 pub require_special: bool,
79
80 pub argon2_config: Argon2Config,
82}
83
84#[derive(Debug, Clone)]
86pub struct Argon2Config {
87 pub memory_cost: u32,
88 pub time_cost: u32,
89 pub parallelism: u32,
90}
91
92#[derive(Debug, Clone)]
93pub enum SameSite {
94 Strict,
95 Lax,
96 None,
97}
98
99impl Default for AuthConfig {
100 fn default() -> Self {
101 Self {
102 secret: String::new(),
103 base_url: "http://localhost:3000".to_string(),
104 session: SessionConfig::default(),
105 jwt: JwtConfig::default(),
106 password: PasswordConfig::default(),
107 email_provider: None,
108 }
109 }
110}
111
112impl Default for SessionConfig {
113 fn default() -> Self {
114 Self {
115 expires_in: Duration::hours(24 * 7), update_age: true,
117 cookie_name: "better-auth.session-token".to_string(),
118 cookie_secure: true,
119 cookie_http_only: true,
120 cookie_same_site: SameSite::Lax,
121 }
122 }
123}
124
125impl Default for JwtConfig {
126 fn default() -> Self {
127 Self {
128 expires_in: Duration::hours(24), algorithm: "HS256".to_string(),
130 issuer: None,
131 audience: None,
132 }
133 }
134}
135
136impl Default for PasswordConfig {
137 fn default() -> Self {
138 Self {
139 min_length: 8,
140 require_uppercase: false,
141 require_lowercase: false,
142 require_numbers: false,
143 require_special: false,
144 argon2_config: Argon2Config::default(),
145 }
146 }
147}
148
149impl Default for Argon2Config {
150 fn default() -> Self {
151 Self {
152 memory_cost: 4096, time_cost: 3, parallelism: 1, }
156 }
157}
158
159impl AuthConfig {
160 pub fn new(secret: impl Into<String>) -> Self {
161 Self {
162 secret: secret.into(),
163 ..Default::default()
164 }
165 }
166
167 pub fn base_url(mut self, url: impl Into<String>) -> Self {
168 self.base_url = url.into();
169 self
170 }
171
172 pub fn session_expires_in(mut self, duration: Duration) -> Self {
173 self.session.expires_in = duration;
174 self
175 }
176
177 pub fn jwt_expires_in(mut self, duration: Duration) -> Self {
178 self.jwt.expires_in = duration;
179 self
180 }
181
182 pub fn password_min_length(mut self, length: usize) -> Self {
183 self.password.min_length = length;
184 self
185 }
186
187 pub fn validate(&self) -> Result<(), AuthError> {
188 if self.secret.is_empty() {
189 return Err(AuthError::config("Secret key cannot be empty"));
190 }
191
192 if self.secret.len() < 32 {
193 return Err(AuthError::config(
194 "Secret key must be at least 32 characters",
195 ));
196 }
197
198 Ok(())
199 }
200}