better_auth-stripe 0.6.2 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/better_auth/stripe/middleware.rb +16 -0
- data/lib/better_auth/stripe/routes/cancel_subscription.rb +1 -0
- data/lib/better_auth/stripe/routes/cancel_subscription_callback.rb +1 -0
- data/lib/better_auth/stripe/routes/create_billing_portal.rb +1 -0
- data/lib/better_auth/stripe/routes/stripe_webhook.rb +15 -9
- data/lib/better_auth/stripe/routes/subscription_success.rb +1 -0
- data/lib/better_auth/stripe/routes/upgrade_subscription.rb +1 -0
- data/lib/better_auth/stripe/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1858dc05175fb2101ce2afb5f74a3e7de80a9b88c96a7980fbd7b6bfcac6afcc
|
|
4
|
+
data.tar.gz: f3f683695cb0f73a2f8d5aca655f9cd8b040fa97e26fadac1300096488cc783f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fbb99518f0ad2849d066462f0fa1cbfb0a6451c741eac7aa45d86a6176b03c03543eccd58dc60ecd5df25898c10739d9ce8b033446fc8264822c1754450b4ff1
|
|
7
|
+
data.tar.gz: f876d15cc9690af96b0b864665a767bd6dddeac4ed8508bede47b78e874a9917e0d032bbc43f77980cc2d27bab89f5f1ea726f60ab97d13cb4ed6734bd170006
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.7.0] - 2026-05-05
|
|
6
|
+
|
|
7
|
+
- Changed Stripe webhooks to reject requests when the configured Stripe client does not expose `webhooks.construct_event_async` or `webhooks.construct_event`, preventing unverified payload processing.
|
|
8
|
+
- Hardened Stripe subscription route middleware and webhook origin handling with regression coverage.
|
|
9
|
+
|
|
5
10
|
## [0.6.0] - 2026-05-02
|
|
6
11
|
|
|
7
12
|
- Modularized the Stripe plugin into upstream-aligned client, schema, middleware, hooks, route, metadata, type, and utility modules while keeping the existing public facade.
|
|
@@ -47,6 +47,22 @@ module BetterAuth
|
|
|
47
47
|
|
|
48
48
|
nil
|
|
49
49
|
end
|
|
50
|
+
|
|
51
|
+
def validate_trusted_url!(ctx, value, label)
|
|
52
|
+
return if value.nil? || value.to_s.empty?
|
|
53
|
+
|
|
54
|
+
validation_value = value.to_s.gsub("{CHECKOUT_SESSION_ID}", "checkout_session_id")
|
|
55
|
+
return if ctx.context.trusted_origin?(validation_value, allow_relative_paths: true)
|
|
56
|
+
|
|
57
|
+
raise APIError.new("FORBIDDEN", message: "Invalid #{label}")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def validate_trusted_urls!(ctx, source, mapping)
|
|
61
|
+
body = BetterAuth::Plugins.normalize_hash(source || {})
|
|
62
|
+
mapping.each do |key, label|
|
|
63
|
+
validate_trusted_url!(ctx, body[key], label)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
50
66
|
end
|
|
51
67
|
end
|
|
52
68
|
end
|
|
@@ -10,6 +10,7 @@ module BetterAuth
|
|
|
10
10
|
BetterAuth::Endpoint.new(path: "/subscription/cancel", method: "POST") do |ctx|
|
|
11
11
|
session = BetterAuth::Routes.current_session(ctx)
|
|
12
12
|
body = BetterAuth::Plugins.normalize_hash(ctx.body)
|
|
13
|
+
BetterAuth::Stripe::Middleware.validate_trusted_urls!(ctx, body, return_url: "returnUrl")
|
|
13
14
|
customer_type = BetterAuth::Plugins.stripe_customer_type!(body)
|
|
14
15
|
reference_id = BetterAuth::Plugins.stripe_reference_id!(ctx, session, customer_type, body[:reference_id], config)
|
|
15
16
|
BetterAuth::Plugins.stripe_authorize_reference!(ctx, session, reference_id, "cancel-subscription", customer_type, BetterAuth::Plugins.stripe_subscription_options(config), explicit: body.key?(:reference_id))
|
|
@@ -10,6 +10,7 @@ module BetterAuth
|
|
|
10
10
|
BetterAuth::Endpoint.new(path: "/subscription/cancel/callback", method: "GET") do |ctx|
|
|
11
11
|
query = BetterAuth::Plugins.normalize_hash(ctx.query)
|
|
12
12
|
callback = query[:callback_url] || "/"
|
|
13
|
+
BetterAuth::Stripe::Middleware.validate_trusted_url!(ctx, callback, "callbackURL")
|
|
13
14
|
unless query[:subscription_id]
|
|
14
15
|
raise ctx.redirect(BetterAuth::Plugins.stripe_url(ctx, callback))
|
|
15
16
|
end
|
|
@@ -10,6 +10,7 @@ module BetterAuth
|
|
|
10
10
|
BetterAuth::Endpoint.new(path: "/subscription/billing-portal", method: "POST") do |ctx|
|
|
11
11
|
session = BetterAuth::Routes.current_session(ctx)
|
|
12
12
|
body = BetterAuth::Plugins.normalize_hash(ctx.body)
|
|
13
|
+
BetterAuth::Stripe::Middleware.validate_trusted_urls!(ctx, body, return_url: "returnUrl")
|
|
13
14
|
customer_type = BetterAuth::Plugins.stripe_customer_type!(body)
|
|
14
15
|
reference_id = BetterAuth::Plugins.stripe_reference_id!(ctx, session, customer_type, body[:reference_id], config)
|
|
15
16
|
BetterAuth::Plugins.stripe_authorize_reference!(ctx, session, reference_id, "billing-portal", customer_type, BetterAuth::Plugins.stripe_subscription_options(config), explicit: body.key?(:reference_id))
|
|
@@ -7,23 +7,29 @@ module BetterAuth
|
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
9
|
def endpoint(config)
|
|
10
|
-
BetterAuth::Endpoint.new(path: "/stripe/webhook", method: "POST") do |ctx|
|
|
10
|
+
BetterAuth::Endpoint.new(path: "/stripe/webhook", method: "POST", disable_body: true) do |ctx|
|
|
11
11
|
signature = ctx.headers["stripe-signature"]
|
|
12
12
|
raise BetterAuth::APIError.new("BAD_REQUEST", message: BetterAuth::Stripe::ERROR_CODES.fetch("STRIPE_SIGNATURE_NOT_FOUND")) if signature.to_s.empty?
|
|
13
13
|
|
|
14
14
|
raise BetterAuth::APIError.new("INTERNAL_SERVER_ERROR", message: BetterAuth::Stripe::ERROR_CODES.fetch("STRIPE_WEBHOOK_SECRET_NOT_FOUND")) if config[:stripe_webhook_secret].to_s.empty?
|
|
15
15
|
|
|
16
|
+
payload = ctx.raw_body.to_s.empty? ? ctx.body : ctx.raw_body
|
|
16
17
|
event = begin
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
client = BetterAuth::Plugins.stripe_client(config)
|
|
19
|
+
webhooks = client.webhooks if client.respond_to?(:webhooks)
|
|
20
|
+
unless webhooks
|
|
21
|
+
raise BetterAuth::APIError.new("BAD_REQUEST", message: BetterAuth::Stripe::ERROR_CODES.fetch("FAILED_TO_CONSTRUCT_STRIPE_EVENT"))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if webhooks.respond_to?(:construct_event_async)
|
|
25
|
+
webhooks.construct_event_async(payload, signature, config[:stripe_webhook_secret])
|
|
26
|
+
elsif webhooks.respond_to?(:construct_event)
|
|
27
|
+
webhooks.construct_event(payload, signature, config[:stripe_webhook_secret])
|
|
24
28
|
else
|
|
25
|
-
|
|
29
|
+
raise BetterAuth::APIError.new("BAD_REQUEST", message: BetterAuth::Stripe::ERROR_CODES.fetch("FAILED_TO_CONSTRUCT_STRIPE_EVENT"))
|
|
26
30
|
end
|
|
31
|
+
rescue BetterAuth::APIError
|
|
32
|
+
raise
|
|
27
33
|
rescue
|
|
28
34
|
raise BetterAuth::APIError.new("BAD_REQUEST", message: BetterAuth::Stripe::ERROR_CODES.fetch("FAILED_TO_CONSTRUCT_STRIPE_EVENT"))
|
|
29
35
|
end
|
|
@@ -10,6 +10,7 @@ module BetterAuth
|
|
|
10
10
|
BetterAuth::Endpoint.new(path: "/subscription/success", method: "GET") do |ctx|
|
|
11
11
|
query = BetterAuth::Plugins.normalize_hash(ctx.query)
|
|
12
12
|
callback = query[:callback_url] || "/"
|
|
13
|
+
BetterAuth::Stripe::Middleware.validate_trusted_url!(ctx, callback, "callbackURL")
|
|
13
14
|
checkout_session_id = query[:checkout_session_id]
|
|
14
15
|
subscription_id = query[:subscription_id]
|
|
15
16
|
if checkout_session_id
|
|
@@ -10,6 +10,7 @@ module BetterAuth
|
|
|
10
10
|
BetterAuth::Endpoint.new(path: "/subscription/upgrade", method: "POST") do |ctx|
|
|
11
11
|
session = BetterAuth::Routes.current_session(ctx)
|
|
12
12
|
body = BetterAuth::Plugins.normalize_hash(ctx.body)
|
|
13
|
+
BetterAuth::Stripe::Middleware.validate_trusted_urls!(ctx, body, success_url: "successUrl", cancel_url: "cancelUrl", return_url: "returnUrl")
|
|
13
14
|
subscription_options = BetterAuth::Plugins.stripe_subscription_options(config)
|
|
14
15
|
customer_type = BetterAuth::Plugins.stripe_customer_type!(body)
|
|
15
16
|
reference_id = BetterAuth::Plugins.stripe_reference_id!(ctx, session, customer_type, body[:reference_id], config)
|