Class: BetterAuth::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/better_auth/configuration.rb

Constant Summary collapse

DEFAULT_BASE_PATH =
"/api/auth"
DEFAULT_SECRET =
"better-auth-secret-12345678901234567890"
DEFAULT_SESSION =
{
  update_age: 24 * 60 * 60,
  expires_in: 60 * 60 * 24 * 7,
  fresh_age: 60 * 60 * 24
}.freeze
DEFAULT_EMAIL_AND_PASSWORD =
{
  min_password_length: 8,
  max_password_length: 128
}.freeze
DEFAULT_PASSWORD_HASHER =
:scrypt
SUPPORTED_PASSWORD_HASHERS =
[:scrypt, :bcrypt].freeze
DEFAULT_STATELESS_SESSION =
{
  cookie_cache: {
    enabled: true,
    strategy: "jwe",
    refresh_cache: true
  }
}.freeze
DEFAULT_STATELESS_ACCOUNT =
{
  store_state_strategy: "cookie",
  store_account_cookie: true
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Configuration

Returns a new instance of Configuration.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/better_auth/configuration.rb', line 64

def initialize(options = {})
  @configured_social_provider_ids = extract_configured_social_provider_ids(options)
  options = symbolize_keys(options)
  @explicit_options = deep_dup(options)

  @logger = options[:logger]
  @app_name = options[:app_name] || "Better Auth"
  @base_path = normalize_base_path(options.fetch(:base_path, DEFAULT_BASE_PATH))
  @database = options[:database]
  @secondary_storage = options[:secondary_storage]
  @plugins = normalize_plugins(options[:plugins])
  @advanced = deep_merge({}, symbolize_keys(options[:advanced] || {}))
  @disabled_paths = Array(options[:disabled_paths]).compact.map(&:to_s)
  @database_hooks = options[:database_hooks]
  @hooks = options[:hooks]
  @on_api_error = symbolize_keys(options[:on_api_error] || options[:on_apierror] || {})
  @telemetry = symbolize_keys(options[:telemetry] || {})
  @social_providers = normalize_social_providers(options[:social_providers])
  @trusted_origins_callbacks = []
  @trusted_origins_callbacks << options[:trusted_origins] if options[:trusted_origins].respond_to?(:call)
  @trusted_origins_callback = combined_trusted_origins_callback
  legacy_secret = resolve_secret(options, allow_test_default: false)
  secrets = options.key?(:secrets) ? options[:secrets] : SecretConfig.parse_env(Env.get("BETTER_AUTH_SECRETS"))
  if secrets
    @secret_config = SecretConfig.build(secrets, legacy_secret, logger: logger)
    @secret = @secret_config.current_secret
  else
    @secret = legacy_secret || (test_environment? ? DEFAULT_SECRET : nil)
    @secret_config = @secret
  end
  @base_url, @context_base_url = normalize_base_url(options[:base_url])
  @serving_origins = normalize_serving_origins(options[:serving_origins])
  @session = normalize_session(options[:session])
  @account = (options[:account])
  @user = symbolize_keys(options[:user] || {})
  @verification = symbolize_keys(options[:verification] || {})
  @email_and_password = normalize_email_and_password(options[:email_and_password])
  @password_hasher = normalize_password_hasher(options[:password_hasher])
  @email_verification = symbolize_keys(options[:email_verification] || {})
  @experimental = normalize_experimental(options[:experimental])
  @rate_limit = normalize_rate_limit(options[:rate_limit])
  @trusted_origins = normalize_trusted_origins(options[:trusted_origins])

  validate_secret
end

Instance Attribute Details

#accountObject (readonly)

Returns the value of attribute account.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def 
  @account
end

#advancedObject (readonly)

Returns the value of attribute advanced.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def advanced
  @advanced
end

#app_nameObject (readonly)

Returns the value of attribute app_name.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def app_name
  @app_name
end

#base_pathObject (readonly)

Returns the value of attribute base_path.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def base_path
  @base_path
end

#base_urlObject (readonly)

Returns the value of attribute base_url.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def base_url
  @base_url
end

#configured_social_provider_idsObject (readonly)

Returns the value of attribute configured_social_provider_ids.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def configured_social_provider_ids
  @configured_social_provider_ids
end

#context_base_urlObject (readonly)

Returns the value of attribute context_base_url.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def context_base_url
  @context_base_url
end

#databaseObject (readonly)

Returns the value of attribute database.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def database
  @database
end

#database_hooksObject (readonly)

Returns the value of attribute database_hooks.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def database_hooks
  @database_hooks
end

#disabled_pathsObject (readonly)

Returns the value of attribute disabled_paths.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def disabled_paths
  @disabled_paths
end

#email_and_passwordObject (readonly)

Returns the value of attribute email_and_password.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def email_and_password
  @email_and_password
end

#email_verificationObject (readonly)

Returns the value of attribute email_verification.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def email_verification
  @email_verification
end

#experimentalObject (readonly)

Returns the value of attribute experimental.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def experimental
  @experimental
end

#hooksObject (readonly)

Returns the value of attribute hooks.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def hooks
  @hooks
end

#loggerObject (readonly)

Returns the value of attribute logger.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def logger
  @logger
end

#on_api_errorObject (readonly)

Returns the value of attribute on_api_error.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def on_api_error
  @on_api_error
end

#password_hasherObject (readonly)

Returns the value of attribute password_hasher.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def password_hasher
  @password_hasher
end

#pluginsObject (readonly)

Returns the value of attribute plugins.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def plugins
  @plugins
end

#rate_limitObject (readonly)

Returns the value of attribute rate_limit.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def rate_limit
  @rate_limit
end

#secondary_storageObject (readonly)

Returns the value of attribute secondary_storage.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def secondary_storage
  @secondary_storage
end

#secretObject (readonly)

Returns the value of attribute secret.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def secret
  @secret
end

#secret_configObject (readonly)

Returns the value of attribute secret_config.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def secret_config
  @secret_config
end

#serving_originsObject (readonly)

Returns the value of attribute serving_origins.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def serving_origins
  @serving_origins
end

#sessionObject (readonly)

Returns the value of attribute session.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def session
  @session
end

#social_providersObject (readonly)

Returns the value of attribute social_providers.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def social_providers
  @social_providers
end

#telemetryObject (readonly)

Returns the value of attribute telemetry.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def telemetry
  @telemetry
end

#trusted_originsObject (readonly)

Returns the value of attribute trusted_origins.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def trusted_origins
  @trusted_origins
end

#trusted_origins_callbackObject (readonly)

Returns the value of attribute trusted_origins_callback.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def trusted_origins_callback
  @trusted_origins_callback
end

#userObject (readonly)

Returns the value of attribute user.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def user
  @user
end

#verificationObject (readonly)

Returns the value of attribute verification.



33
34
35
# File 'lib/better_auth/configuration.rb', line 33

def verification
  @verification
end

Class Method Details

.matches_origin_pattern?(url, pattern, allow_relative_paths: false) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/better_auth/configuration.rb', line 173

def self.matches_origin_pattern?(url, pattern, allow_relative_paths: false)
  return relative_path_allowed?(url) if url.start_with?("/") && allow_relative_paths
  return false if url.start_with?("/")

  uri = parse_uri(url)
  return false unless uri

  if pattern.include?("*") || pattern.include?("?")
    if pattern.include?("://")
      origin = origin_for(uri)
      return true if origin && wildcard_match?(pattern, origin)

      return wildcard_match?(pattern, url)
    end

    return wildcard_match?(pattern, uri.host.to_s)
  end

  protocol = uri.scheme&.then { |scheme| "#{scheme}:" }
  if protocol == "http:" || protocol == "https:" || protocol.nil?
    pattern == origin_for(uri)
  else
    url.start_with?(pattern)
  end
end

.origin_for(uri) ⇒ Object



209
210
211
212
213
214
215
216
217
218
# File 'lib/better_auth/configuration.rb', line 209

def self.origin_for(uri)
  return nil unless uri.scheme && uri.host

  port = uri.port
  default_port = (uri.scheme == "http" && port == 80) || (uri.scheme == "https" && port == 443)
  host = uri.host
  host = "[#{host}]" if host.include?(":") && !host.start_with?("[")
  origin = "#{uri.scheme}://#{host}"
  default_port ? origin : "#{origin}:#{port}"
end

.parse_uri(url) ⇒ Object



203
204
205
206
207
# File 'lib/better_auth/configuration.rb', line 203

def self.parse_uri(url)
  URI.parse(url)
rescue URI::InvalidURIError
  nil
end

.relative_path_allowed?(url) ⇒ Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/better_auth/configuration.rb', line 199

def self.relative_path_allowed?(url)
  %r{\A/(?!/|\\|%2f|%5c)[\w\-.+/@]*(?:\?[\w\-.+/=&%@]*)?\z}i.match?(url)
end

.wildcard_match?(pattern, value) ⇒ Boolean

Returns:

  • (Boolean)


220
221
222
223
# File 'lib/better_auth/configuration.rb', line 220

def self.wildcard_match?(pattern, value)
  regex = Regexp.escape(pattern).gsub("\\*", ".*").gsub("\\?", ".")
  /\A#{regex}\z/.match?(value)
end

Instance Method Details

#explicit_trusted_originsObject



116
117
118
119
120
121
# File 'lib/better_auth/configuration.rb', line 116

def explicit_trusted_origins
  configured = @explicit_options[:trusted_origins]
  origins = configured.respond_to?(:call) ? [] : Array(configured).compact
  origins.concat(env_trusted_origins)
  origins.map(&:to_s).reject(&:empty?).uniq
end

#merge_defaults!(defaults) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/better_auth/configuration.rb', line 158

def merge_defaults!(defaults)
  normalized = symbolize_keys(defaults || {})
  normalized.each do |key, value|
    next unless respond_to?(key)
    next if key == :database_hooks || key == :configured_social_provider_ids

    if key == :trusted_origins
      merge_trusted_origins_default(value)
      next
    end

    instance_variable_set("@#{key}", merge_default_value([key], public_send(key), value))
  end
end

#production?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/better_auth/configuration.rb', line 123

def production?
  production_environment?
end

#to_hObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/better_auth/configuration.rb', line 127

def to_h
  {
    app_name: app_name,
    base_url: base_url,
    base_path: base_path,
    secret: secret,
    secret_config: secret_config,
    database: database,
    plugins: plugins,
    trusted_origins: trusted_origins,
    serving_origins: serving_origins,
    rate_limit: rate_limit,
    session: session,
    account: ,
    user: user,
    verification: verification,
    advanced: advanced,
    email_and_password: email_and_password,
    password_hasher: password_hasher,
    email_verification: email_verification,
    social_providers: social_providers,
    experimental: experimental,
    secondary_storage: secondary_storage,
    database_hooks: database_hooks,
    hooks: hooks,
    on_api_error: on_api_error,
    disabled_paths: disabled_paths,
    telemetry: telemetry
  }
end

#trusted_origin?(url, allow_relative_paths: false) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
# File 'lib/better_auth/configuration.rb', line 110

def trusted_origin?(url, allow_relative_paths: false)
  trusted_origins.any? do |origin|
    self.class.matches_origin_pattern?(url, origin, allow_relative_paths: allow_relative_paths)
  end
end