better_auth 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/README.md +5 -3
  4. data/lib/better_auth/adapters/internal_adapter.rb +173 -20
  5. data/lib/better_auth/adapters/memory.rb +61 -12
  6. data/lib/better_auth/adapters/mongodb.rb +5 -365
  7. data/lib/better_auth/adapters/sql.rb +44 -3
  8. data/lib/better_auth/api.rb +7 -2
  9. data/lib/better_auth/async.rb +70 -0
  10. data/lib/better_auth/context.rb +2 -1
  11. data/lib/better_auth/database_hooks.rb +3 -3
  12. data/lib/better_auth/deprecate.rb +28 -0
  13. data/lib/better_auth/endpoint.rb +5 -2
  14. data/lib/better_auth/host.rb +166 -0
  15. data/lib/better_auth/instrumentation.rb +74 -0
  16. data/lib/better_auth/logger.rb +31 -0
  17. data/lib/better_auth/middleware/origin_check.rb +2 -2
  18. data/lib/better_auth/oauth2.rb +94 -0
  19. data/lib/better_auth/plugin.rb +14 -1
  20. data/lib/better_auth/plugins/email_otp.rb +16 -5
  21. data/lib/better_auth/plugins/generic_oauth.rb +14 -28
  22. data/lib/better_auth/plugins/oauth_protocol.rb +553 -64
  23. data/lib/better_auth/plugins/organization/schema.rb +6 -0
  24. data/lib/better_auth/plugins/organization.rb +56 -20
  25. data/lib/better_auth/plugins/two_factor.rb +53 -18
  26. data/lib/better_auth/rate_limiter.rb +37 -2
  27. data/lib/better_auth/request_state.rb +44 -0
  28. data/lib/better_auth/router.rb +14 -1
  29. data/lib/better_auth/routes/account.rb +16 -4
  30. data/lib/better_auth/routes/email_verification.rb +5 -2
  31. data/lib/better_auth/routes/password.rb +21 -1
  32. data/lib/better_auth/routes/session.rb +27 -4
  33. data/lib/better_auth/routes/sign_in.rb +3 -1
  34. data/lib/better_auth/routes/sign_up.rb +60 -1
  35. data/lib/better_auth/routes/social.rb +231 -22
  36. data/lib/better_auth/routes/user.rb +23 -5
  37. data/lib/better_auth/schema/sql.rb +11 -0
  38. data/lib/better_auth/schema.rb +16 -0
  39. data/lib/better_auth/session.rb +12 -1
  40. data/lib/better_auth/social_providers/apple.rb +44 -8
  41. data/lib/better_auth/social_providers/atlassian.rb +32 -0
  42. data/lib/better_auth/social_providers/base.rb +262 -4
  43. data/lib/better_auth/social_providers/cognito.rb +32 -0
  44. data/lib/better_auth/social_providers/discord.rb +27 -5
  45. data/lib/better_auth/social_providers/dropbox.rb +33 -0
  46. data/lib/better_auth/social_providers/facebook.rb +35 -0
  47. data/lib/better_auth/social_providers/figma.rb +31 -0
  48. data/lib/better_auth/social_providers/github.rb +21 -6
  49. data/lib/better_auth/social_providers/gitlab.rb +16 -3
  50. data/lib/better_auth/social_providers/google.rb +38 -13
  51. data/lib/better_auth/social_providers/huggingface.rb +31 -0
  52. data/lib/better_auth/social_providers/kakao.rb +32 -0
  53. data/lib/better_auth/social_providers/kick.rb +32 -0
  54. data/lib/better_auth/social_providers/line.rb +33 -0
  55. data/lib/better_auth/social_providers/linear.rb +44 -0
  56. data/lib/better_auth/social_providers/linkedin.rb +30 -0
  57. data/lib/better_auth/social_providers/microsoft_entra_id.rb +79 -7
  58. data/lib/better_auth/social_providers/naver.rb +31 -0
  59. data/lib/better_auth/social_providers/notion.rb +33 -0
  60. data/lib/better_auth/social_providers/paybin.rb +31 -0
  61. data/lib/better_auth/social_providers/paypal.rb +36 -0
  62. data/lib/better_auth/social_providers/polar.rb +31 -0
  63. data/lib/better_auth/social_providers/railway.rb +49 -0
  64. data/lib/better_auth/social_providers/reddit.rb +32 -0
  65. data/lib/better_auth/social_providers/roblox.rb +31 -0
  66. data/lib/better_auth/social_providers/salesforce.rb +38 -0
  67. data/lib/better_auth/social_providers/slack.rb +30 -0
  68. data/lib/better_auth/social_providers/spotify.rb +31 -0
  69. data/lib/better_auth/social_providers/tiktok.rb +35 -0
  70. data/lib/better_auth/social_providers/twitch.rb +39 -0
  71. data/lib/better_auth/social_providers/twitter.rb +32 -0
  72. data/lib/better_auth/social_providers/vercel.rb +47 -0
  73. data/lib/better_auth/social_providers/vk.rb +34 -0
  74. data/lib/better_auth/social_providers/wechat.rb +104 -0
  75. data/lib/better_auth/social_providers/zoom.rb +31 -0
  76. data/lib/better_auth/social_providers.rb +29 -0
  77. data/lib/better_auth/url_helpers.rb +195 -0
  78. data/lib/better_auth/version.rb +1 -1
  79. data/lib/better_auth.rb +8 -1
  80. metadata +38 -15
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module SocialProviders
5
+ module_function
6
+
7
+ def vk(client_id:, client_secret:, scopes: ["email", "phone"], **options)
8
+ Base.oauth_provider(
9
+ id: "vk",
10
+ name: "VK",
11
+ client_id: client_id,
12
+ client_secret: client_secret,
13
+ authorization_endpoint: "https://id.vk.com/authorize",
14
+ token_endpoint: "https://id.vk.com/oauth2/auth",
15
+ user_info_endpoint: "https://id.vk.com/oauth2/user_info",
16
+ user_info_method: :post,
17
+ user_info_body: {client_id: client_id},
18
+ scopes: scopes,
19
+ pkce: true,
20
+ profile_map: ->(profile) {
21
+ user = profile["user"] || profile
22
+ {
23
+ id: user["user_id"],
24
+ name: [user["first_name"], user["last_name"]].compact.join(" "),
25
+ email: user["email"],
26
+ image: user["avatar"],
27
+ emailVerified: false
28
+ }
29
+ },
30
+ **options
31
+ )
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module SocialProviders
5
+ module_function
6
+
7
+ def wechat(client_id:, client_secret:, scopes: ["snsapi_login"], **options)
8
+ normalized = Base.normalize_options(options)
9
+ provider = Base.oauth_provider(
10
+ id: "wechat",
11
+ name: "WeChat",
12
+ client_id: client_id,
13
+ client_secret: client_secret,
14
+ authorization_endpoint: "https://open.weixin.qq.com/connect/qrconnect",
15
+ token_endpoint: "https://api.weixin.qq.com/sns/oauth2/access_token",
16
+ user_info_endpoint: "https://api.weixin.qq.com/sns/userinfo",
17
+ scopes: scopes,
18
+ scope_separator: ",",
19
+ profile_map: ->(profile) {
20
+ {
21
+ id: profile["unionid"] || profile["openid"],
22
+ name: profile["nickname"],
23
+ email: profile["email"],
24
+ image: profile["headimgurl"],
25
+ emailVerified: false
26
+ }
27
+ },
28
+ **options
29
+ )
30
+ provider[:create_authorization_url] = lambda do |data|
31
+ "#{Base.authorization_url("https://open.weixin.qq.com/connect/qrconnect", {
32
+ appid: client_id,
33
+ redirect_uri: normalized[:redirect_uri] || data[:redirect_uri] || data[:redirectURI],
34
+ response_type: "code",
35
+ scope: Base.selected_scopes(scopes, normalized, data).join(","),
36
+ state: data[:state],
37
+ lang: options[:lang] || "cn"
38
+ })}#wechat_redirect"
39
+ end
40
+ provider[:validate_authorization_code] = lambda do |data|
41
+ url = Base.authorization_url("https://api.weixin.qq.com/sns/oauth2/access_token", {
42
+ appid: client_id,
43
+ secret: client_secret,
44
+ code: data[:code],
45
+ grant_type: "authorization_code"
46
+ })
47
+ payload = Base.get_json(url)
48
+ if !payload || payload["errcode"]
49
+ raise Error, "Failed to validate authorization code: #{payload&.fetch("errmsg", nil) || "Unknown error"}"
50
+ end
51
+
52
+ Base.normalize_tokens(payload).merge(
53
+ "openid" => payload["openid"],
54
+ "unionid" => payload["unionid"]
55
+ ).compact
56
+ end
57
+ provider[:refresh_access_token] = normalized[:refresh_access_token] || lambda do |refresh_token|
58
+ url = Base.authorization_url("https://api.weixin.qq.com/sns/oauth2/refresh_token", {
59
+ appid: client_id,
60
+ grant_type: "refresh_token",
61
+ refresh_token: refresh_token
62
+ })
63
+ payload = Base.get_json(url)
64
+ if !payload || payload["errcode"]
65
+ raise Error, "Failed to refresh access token: #{payload&.fetch("errmsg", nil) || "Unknown error"}"
66
+ end
67
+
68
+ Base.normalize_tokens(payload).merge(
69
+ "openid" => payload["openid"],
70
+ "unionid" => payload["unionid"]
71
+ ).compact
72
+ end
73
+ provider[:get_user_info] = lambda do |tokens|
74
+ custom = normalized[:get_user_info]
75
+ next custom.call(tokens) if custom
76
+
77
+ openid = tokens["openid"] || tokens[:openid]
78
+ next nil if openid.to_s.empty?
79
+
80
+ url = Base.authorization_url("https://api.weixin.qq.com/sns/userinfo", {
81
+ access_token: Base.access_token(tokens),
82
+ openid: openid,
83
+ lang: "zh_CN"
84
+ })
85
+ profile = Base.get_json(url)
86
+ next nil if !profile || profile["errcode"]
87
+
88
+ user = Base.apply_profile_mapping(
89
+ {
90
+ id: profile["unionid"] || profile["openid"] || openid,
91
+ name: profile["nickname"],
92
+ email: profile["email"],
93
+ image: profile["headimgurl"],
94
+ emailVerified: false
95
+ },
96
+ profile,
97
+ normalized
98
+ )
99
+ {user: user, data: profile}
100
+ end
101
+ provider
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterAuth
4
+ module SocialProviders
5
+ module_function
6
+
7
+ def zoom(client_id:, client_secret:, scopes: [], **options)
8
+ Base.oauth_provider(
9
+ id: "zoom",
10
+ name: "Zoom",
11
+ client_id: client_id,
12
+ client_secret: client_secret,
13
+ authorization_endpoint: "https://zoom.us/oauth/authorize",
14
+ token_endpoint: "https://zoom.us/oauth/token",
15
+ user_info_endpoint: "https://api.zoom.us/v2/users/me",
16
+ scopes: scopes,
17
+ pkce: options.fetch(:pkce, true),
18
+ profile_map: ->(profile) {
19
+ {
20
+ id: profile["id"],
21
+ name: profile["display_name"],
22
+ email: profile["email"],
23
+ image: profile["pic_url"],
24
+ emailVerified: !!profile["verified"]
25
+ }
26
+ },
27
+ **options
28
+ )
29
+ end
30
+ end
31
+ end
@@ -7,3 +7,32 @@ require_relative "social_providers/gitlab"
7
7
  require_relative "social_providers/discord"
8
8
  require_relative "social_providers/apple"
9
9
  require_relative "social_providers/microsoft_entra_id"
10
+ require_relative "social_providers/atlassian"
11
+ require_relative "social_providers/cognito"
12
+ require_relative "social_providers/dropbox"
13
+ require_relative "social_providers/facebook"
14
+ require_relative "social_providers/figma"
15
+ require_relative "social_providers/huggingface"
16
+ require_relative "social_providers/kakao"
17
+ require_relative "social_providers/kick"
18
+ require_relative "social_providers/line"
19
+ require_relative "social_providers/linear"
20
+ require_relative "social_providers/linkedin"
21
+ require_relative "social_providers/naver"
22
+ require_relative "social_providers/notion"
23
+ require_relative "social_providers/paybin"
24
+ require_relative "social_providers/paypal"
25
+ require_relative "social_providers/polar"
26
+ require_relative "social_providers/railway"
27
+ require_relative "social_providers/reddit"
28
+ require_relative "social_providers/roblox"
29
+ require_relative "social_providers/salesforce"
30
+ require_relative "social_providers/slack"
31
+ require_relative "social_providers/spotify"
32
+ require_relative "social_providers/tiktok"
33
+ require_relative "social_providers/twitch"
34
+ require_relative "social_providers/twitter"
35
+ require_relative "social_providers/vercel"
36
+ require_relative "social_providers/vk"
37
+ require_relative "social_providers/wechat"
38
+ require_relative "social_providers/zoom"
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module BetterAuth
6
+ module URLHelpers
7
+ module_function
8
+
9
+ def valid_proxy_header?(header, type)
10
+ value = header.to_s
11
+ return false if value.strip.empty?
12
+
13
+ case type.to_sym
14
+ when :proto
15
+ ["http", "https"].include?(value)
16
+ when :host
17
+ return false if value.match?(/\.\.|\0|\s|\A[.]|[<>'"]|javascript:|file:|data:/i)
18
+ return false if value.match?(%r{[/\\]})
19
+
20
+ patterns = [
21
+ /\A[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*(:[0-9]{1,5})?\z/,
22
+ /\A(\d{1,3}\.){3}\d{1,3}(:[0-9]{1,5})?\z/,
23
+ /\A\[[0-9a-fA-F:]+\](:[0-9]{1,5})?\z/,
24
+ /\Alocalhost(:[0-9]{1,5})?\z/i
25
+ ]
26
+ patterns.any? { |pattern| value.match?(pattern) } && valid_port?(value)
27
+ else
28
+ false
29
+ end
30
+ end
31
+
32
+ def matches_host_pattern?(host, pattern)
33
+ return false if host.to_s.empty? || pattern.to_s.empty?
34
+
35
+ normalized_host = normalize_host_pattern_value(host)
36
+ normalized_pattern = normalize_host_pattern_value(pattern)
37
+ regex = Regexp.escape(normalized_pattern)
38
+ .gsub("\\*", ".*")
39
+ .gsub("\\?", ".")
40
+ !!normalized_host.match?(/\A#{regex}\z/i)
41
+ end
42
+
43
+ def host_from_source(source, trusted_proxy_headers: false)
44
+ headers = headers_from_source(source)
45
+ if trusted_proxy_headers
46
+ forwarded_host = header_value(headers, "x-forwarded-host")
47
+ return forwarded_host if forwarded_host && valid_proxy_header?(forwarded_host, :host)
48
+ end
49
+
50
+ host = header_value(headers, "host")
51
+ return host if host && valid_proxy_header?(host, :host)
52
+
53
+ uri_host(source_url(source))
54
+ end
55
+
56
+ def protocol_from_source(source, config_protocol: nil, trusted_proxy_headers: false)
57
+ return config_protocol if ["http", "https"].include?(config_protocol)
58
+
59
+ headers = headers_from_source(source)
60
+ if trusted_proxy_headers
61
+ forwarded_proto = header_value(headers, "x-forwarded-proto")
62
+ return forwarded_proto if forwarded_proto && valid_proxy_header?(forwarded_proto, :proto)
63
+ end
64
+
65
+ protocol = uri_scheme(source_url(source))
66
+ return protocol if ["http", "https"].include?(protocol)
67
+
68
+ host = host_from_source(source, trusted_proxy_headers: trusted_proxy_headers)
69
+ return "http" if host && loopback_for_dev_scheme?(host)
70
+
71
+ "https"
72
+ end
73
+
74
+ def resolve_base_url(config, base_path, source = nil, load_env: true, trusted_proxy_headers: false)
75
+ if dynamic_config?(config)
76
+ return resolve_dynamic_base_url(config, source, base_path, trusted_proxy_headers: trusted_proxy_headers) if source
77
+ return with_path(config[:fallback] || config["fallback"], base_path) if config[:fallback] || config["fallback"]
78
+
79
+ return env_base_url(base_path) if load_env
80
+ return nil
81
+ end
82
+
83
+ return with_path(config, base_path) if config.is_a?(String)
84
+ return env_base_url(base_path) if load_env
85
+ return with_path(origin(source_url(source)), base_path) if source
86
+
87
+ nil
88
+ end
89
+
90
+ def resolve_dynamic_base_url(config, source, base_path, trusted_proxy_headers: false)
91
+ host = host_from_source(source, trusted_proxy_headers: trusted_proxy_headers)
92
+ fallback = config[:fallback] || config["fallback"]
93
+ raise Error, "Could not determine host from request headers. Please provide a fallback URL in your baseURL config." unless host || fallback
94
+
95
+ allowed_hosts = config[:allowed_hosts] || config["allowed_hosts"] || config[:allowedHosts] || config["allowedHosts"] || []
96
+ if host && allowed_hosts.any? { |pattern| matches_host_pattern?(host, pattern) }
97
+ protocol = protocol_from_source(source, config_protocol: config[:protocol] || config["protocol"], trusted_proxy_headers: trusted_proxy_headers)
98
+ return with_path("#{protocol}://#{host}", base_path)
99
+ end
100
+
101
+ return with_path(fallback, base_path) if fallback
102
+
103
+ raise Error, "Host \"#{host}\" is not in the allowed hosts list."
104
+ end
105
+
106
+ def with_path(url, path = "/api/auth")
107
+ parsed = URI.parse(url.to_s)
108
+ raise Error, "Invalid base URL: #{url}. URL must include 'http://' or 'https://'" unless ["http", "https"].include?(parsed.scheme)
109
+
110
+ current_path = parsed.path.to_s.gsub(%r{/+\z}, "")
111
+ return url.to_s if !current_path.empty? && current_path != "/"
112
+
113
+ trimmed = url.to_s.gsub(%r{/+\z}, "")
114
+ return trimmed if path.to_s.empty? || path == "/"
115
+
116
+ suffix = path.start_with?("/") ? path : "/#{path}"
117
+ "#{trimmed}#{suffix}"
118
+ rescue URI::InvalidURIError
119
+ raise Error, "Invalid base URL: #{url}. Please provide a valid base URL."
120
+ end
121
+
122
+ def origin(url)
123
+ parsed = URI.parse(url.to_s)
124
+ return nil unless ["http", "https"].include?(parsed.scheme)
125
+
126
+ port = parsed.port
127
+ default_port = (parsed.scheme == "http" && port == 80) || (parsed.scheme == "https" && port == 443)
128
+ default_port ? "#{parsed.scheme}://#{parsed.host}" : "#{parsed.scheme}://#{parsed.host}:#{port}"
129
+ rescue URI::InvalidURIError
130
+ nil
131
+ end
132
+
133
+ def uri_host(url)
134
+ parsed = URI.parse(url.to_s)
135
+ return nil unless parsed.host
136
+
137
+ default_port = (parsed.scheme == "http" && parsed.port == 80) || (parsed.scheme == "https" && parsed.port == 443)
138
+ default_port ? parsed.host : "#{parsed.host}:#{parsed.port}"
139
+ rescue URI::InvalidURIError
140
+ nil
141
+ end
142
+
143
+ def uri_scheme(url)
144
+ URI.parse(url.to_s).scheme
145
+ rescue URI::InvalidURIError
146
+ nil
147
+ end
148
+
149
+ def normalize_host_pattern_value(value)
150
+ value.to_s.sub(%r{\Ahttps?://}i, "").split("/").first.to_s.downcase
151
+ end
152
+
153
+ def headers_from_source(source)
154
+ return {} unless source
155
+ return source.headers if source.respond_to?(:headers)
156
+ return source if source.is_a?(Hash)
157
+
158
+ {}
159
+ end
160
+
161
+ def header_value(headers, key)
162
+ if headers.respond_to?(:get)
163
+ headers.get(key)
164
+ else
165
+ headers[key] || headers[key.to_s] || headers[key.to_s.downcase] || headers[key.to_s.upcase] || headers[key.tr("-", "_").upcase]
166
+ end
167
+ end
168
+
169
+ def source_url(source)
170
+ source.url if source.respond_to?(:url)
171
+ end
172
+
173
+ def dynamic_config?(config)
174
+ config.is_a?(Hash) && (config.key?(:allowed_hosts) || config.key?("allowed_hosts") || config.key?(:allowedHosts) || config.key?("allowedHosts"))
175
+ end
176
+
177
+ def env_base_url(base_path)
178
+ url = ENV["BETTER_AUTH_URL"] || ENV["NEXT_PUBLIC_BETTER_AUTH_URL"] || ENV["PUBLIC_BETTER_AUTH_URL"] || ENV["NUXT_PUBLIC_BETTER_AUTH_URL"] || ENV["NUXT_PUBLIC_AUTH_URL"]
179
+ url ||= ENV["BASE_URL"] if ENV["BASE_URL"] && ENV["BASE_URL"] != "/"
180
+ url ? with_path(url, base_path) : nil
181
+ end
182
+
183
+ def loopback_for_dev_scheme?(host)
184
+ hostname = host.to_s.sub(/:\d+\z/, "").sub(/\A\[/, "").sub(/\]\z/, "").downcase
185
+ hostname == "localhost" || hostname.end_with?(".localhost") || hostname == "::1" || hostname.start_with?("127.")
186
+ end
187
+
188
+ def valid_port?(host)
189
+ port = host[/:(\d{1,5})\z/, 1]
190
+ return true unless port
191
+
192
+ port.to_i.between?(1, 65_535)
193
+ end
194
+ end
195
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterAuth
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/better_auth.rb CHANGED
@@ -5,6 +5,14 @@ require_relative "better_auth/core"
5
5
  require_relative "better_auth/error"
6
6
  require_relative "better_auth/api_error"
7
7
  require_relative "better_auth/crypto"
8
+ require_relative "better_auth/host"
9
+ require_relative "better_auth/url_helpers"
10
+ require_relative "better_auth/request_state"
11
+ require_relative "better_auth/async"
12
+ require_relative "better_auth/deprecate"
13
+ require_relative "better_auth/logger"
14
+ require_relative "better_auth/instrumentation"
15
+ require_relative "better_auth/oauth2"
8
16
  require_relative "better_auth/password"
9
17
  require_relative "better_auth/plugin"
10
18
  require_relative "better_auth/configuration"
@@ -17,7 +25,6 @@ require_relative "better_auth/adapters/postgres"
17
25
  require_relative "better_auth/adapters/mysql"
18
26
  require_relative "better_auth/adapters/sqlite"
19
27
  require_relative "better_auth/adapters/mssql"
20
- require_relative "better_auth/adapters/mongodb"
21
28
  require_relative "better_auth/database_hooks"
22
29
  require_relative "better_auth/adapters/internal_adapter"
23
30
  require_relative "better_auth/context"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Sala
@@ -217,20 +217,6 @@ dependencies:
217
217
  - - "~>"
218
218
  - !ruby/object:Gem::Version
219
219
  version: '2.0'
220
- - !ruby/object:Gem::Dependency
221
- name: mongo
222
- requirement: !ruby/object:Gem::Requirement
223
- requirements:
224
- - - "~>"
225
- - !ruby/object:Gem::Version
226
- version: '2.21'
227
- type: :development
228
- prerelease: false
229
- version_requirements: !ruby/object:Gem::Requirement
230
- requirements:
231
- - - "~>"
232
- - !ruby/object:Gem::Version
233
- version: '2.21'
234
220
  - !ruby/object:Gem::Dependency
235
221
  name: sequel
236
222
  requirement: !ruby/object:Gem::Requirement
@@ -282,6 +268,7 @@ files:
282
268
  - lib/better_auth/adapters/sqlite.rb
283
269
  - lib/better_auth/api.rb
284
270
  - lib/better_auth/api_error.rb
271
+ - lib/better_auth/async.rb
285
272
  - lib/better_auth/auth.rb
286
273
  - lib/better_auth/configuration.rb
287
274
  - lib/better_auth/context.rb
@@ -290,9 +277,14 @@ files:
290
277
  - lib/better_auth/crypto.rb
291
278
  - lib/better_auth/crypto/jwe.rb
292
279
  - lib/better_auth/database_hooks.rb
280
+ - lib/better_auth/deprecate.rb
293
281
  - lib/better_auth/endpoint.rb
294
282
  - lib/better_auth/error.rb
283
+ - lib/better_auth/host.rb
284
+ - lib/better_auth/instrumentation.rb
285
+ - lib/better_auth/logger.rb
295
286
  - lib/better_auth/middleware/origin_check.rb
287
+ - lib/better_auth/oauth2.rb
296
288
  - lib/better_auth/password.rb
297
289
  - lib/better_auth/plugin.rb
298
290
  - lib/better_auth/plugin_context.rb
@@ -336,6 +328,7 @@ files:
336
328
  - lib/better_auth/plugins/username.rb
337
329
  - lib/better_auth/rate_limiter.rb
338
330
  - lib/better_auth/request_ip.rb
331
+ - lib/better_auth/request_state.rb
339
332
  - lib/better_auth/router.rb
340
333
  - lib/better_auth/routes/account.rb
341
334
  - lib/better_auth/routes/email_verification.rb
@@ -354,12 +347,42 @@ files:
354
347
  - lib/better_auth/session_store.rb
355
348
  - lib/better_auth/social_providers.rb
356
349
  - lib/better_auth/social_providers/apple.rb
350
+ - lib/better_auth/social_providers/atlassian.rb
357
351
  - lib/better_auth/social_providers/base.rb
352
+ - lib/better_auth/social_providers/cognito.rb
358
353
  - lib/better_auth/social_providers/discord.rb
354
+ - lib/better_auth/social_providers/dropbox.rb
355
+ - lib/better_auth/social_providers/facebook.rb
356
+ - lib/better_auth/social_providers/figma.rb
359
357
  - lib/better_auth/social_providers/github.rb
360
358
  - lib/better_auth/social_providers/gitlab.rb
361
359
  - lib/better_auth/social_providers/google.rb
360
+ - lib/better_auth/social_providers/huggingface.rb
361
+ - lib/better_auth/social_providers/kakao.rb
362
+ - lib/better_auth/social_providers/kick.rb
363
+ - lib/better_auth/social_providers/line.rb
364
+ - lib/better_auth/social_providers/linear.rb
365
+ - lib/better_auth/social_providers/linkedin.rb
362
366
  - lib/better_auth/social_providers/microsoft_entra_id.rb
367
+ - lib/better_auth/social_providers/naver.rb
368
+ - lib/better_auth/social_providers/notion.rb
369
+ - lib/better_auth/social_providers/paybin.rb
370
+ - lib/better_auth/social_providers/paypal.rb
371
+ - lib/better_auth/social_providers/polar.rb
372
+ - lib/better_auth/social_providers/railway.rb
373
+ - lib/better_auth/social_providers/reddit.rb
374
+ - lib/better_auth/social_providers/roblox.rb
375
+ - lib/better_auth/social_providers/salesforce.rb
376
+ - lib/better_auth/social_providers/slack.rb
377
+ - lib/better_auth/social_providers/spotify.rb
378
+ - lib/better_auth/social_providers/tiktok.rb
379
+ - lib/better_auth/social_providers/twitch.rb
380
+ - lib/better_auth/social_providers/twitter.rb
381
+ - lib/better_auth/social_providers/vercel.rb
382
+ - lib/better_auth/social_providers/vk.rb
383
+ - lib/better_auth/social_providers/wechat.rb
384
+ - lib/better_auth/social_providers/zoom.rb
385
+ - lib/better_auth/url_helpers.rb
363
386
  - lib/better_auth/version.rb
364
387
  homepage: https://github.com/sebasxsala/better-auth
365
388
  licenses: