Skip to main content

better_auth_core/config/
account.rs

1use super::*;
2/// Account-level configuration: linking, token encryption, sign-in behavior.
3#[derive(Debug, Clone)]
4#[expect(
5    clippy::struct_excessive_bools,
6    reason = "Independent configuration switches model distinct upstream behavior, rather than mutually exclusive states"
7)]
8pub struct AccountConfig {
9    pub additional_fields: crate::field_policy::FieldConfigs,
10    /// Update OAuth tokens on every sign-in (default: true)
11    pub update_account_on_sign_in: bool,
12    /// Account linking settings
13    pub account_linking: AccountLinkingConfig,
14    /// Encrypt OAuth tokens at rest (default: false)
15    pub encrypt_oauth_tokens: bool,
16    /// Store account data in an account cookie for OAuth-backed access token flows.
17    pub store_account_cookie: bool,
18    /// Override the account cookie lifetime in seconds, including fractional
19    /// and nonfinite values. Equivalent to the published account_data cookie's
20    /// maxAge attribute; takes precedence over the integer advanced override.
21    /// None inherits the session cache lifetime (or 300 seconds).
22    pub cookie_max_age: Option<f64>,
23    /// Where to persist OAuth state during the authorization flow. Automatic
24    /// selects database state with a server store, cookie state without one.
25    pub store_state_strategy: OAuthStateStrategy,
26    /// Skip state-cookie verification during callback processing.
27    ///
28    /// This is security-sensitive and should stay disabled in normal use.
29    pub skip_state_cookie_check: bool,
30}
31
32/// Settings that control how OAuth accounts are linked to existing users.
33#[derive(Debug, Clone)]
34#[expect(
35    clippy::struct_excessive_bools,
36    reason = "Independent configuration switches model distinct upstream behavior, rather than mutually exclusive states"
37)]
38pub struct AccountLinkingConfig {
39    /// Enable account linking (default: true)
40    pub enabled: bool,
41    /// Providers trusted for linking even when their email is unverified.
42    /// Empty does not bypass the provider email-verification requirement.
43    pub trusted_providers: Vec<String>,
44    /// Optional async policy replacing the static list at init and per request.
45    pub trusted_providers_resolver: Option<std::sync::Arc<dyn TrustedProvidersResolver>>,
46    /// Allow linking accounts with different emails (default: false) - SECURITY WARNING
47    pub allow_different_emails: bool,
48    /// Allow unlinking all accounts (default: false)
49    pub allow_unlinking_all: bool,
50    /// Disable implicit linking during sign-in; only explicit link-social may link.
51    pub disable_implicit_linking: bool,
52    /// Require the *existing local* account's email to be verified before a
53    /// social account may be linked to it implicitly (default: true).
54    pub require_local_email_verified: bool,
55    /// Update user info when a new account is linked (default: false)
56    pub update_user_info_on_link: bool,
57}
58
59/// Strategy for persisting OAuth state between the sign-in and callback steps.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
61pub enum OAuthStateStrategy {
62    /// Select the deployment default during builder initialization. Initialized
63    /// contexts never retain this variant. Low-level uninitialized contexts
64    /// keep the historical database fallback for compatibility.
65    #[default]
66    Automatic,
67    /// Persist state in an encrypted cookie.
68    Cookie,
69    /// Persist state in the verification store plus a signed state cookie.
70    Database,
71}
72
73impl Default for AccountConfig {
74    fn default() -> Self {
75        Self {
76            additional_fields: crate::field_policy::FieldConfigs::new(),
77            update_account_on_sign_in: true,
78            account_linking: AccountLinkingConfig::default(),
79            encrypt_oauth_tokens: false,
80            store_account_cookie: false,
81            cookie_max_age: None,
82            store_state_strategy: OAuthStateStrategy::Automatic,
83            skip_state_cookie_check: false,
84        }
85    }
86}
87
88impl Default for AccountLinkingConfig {
89    fn default() -> Self {
90        Self {
91            enabled: true,
92            trusted_providers: Vec::new(),
93            trusted_providers_resolver: None,
94            allow_different_emails: false,
95            allow_unlinking_all: false,
96            disable_implicit_linking: false,
97            require_local_email_verified: true,
98            update_user_info_on_link: false,
99        }
100    }
101}