In production, require customer_id be passed also.

Stephen Paul Weber created

As a security measure, so people can't modify the cards on arbitrary JIDs.

Change summary

config.ru               | 21 +++++++++++++++++----
views/credit_cards.slim |  1 +
2 files changed, 18 insertions(+), 4 deletions(-)

Detailed changes

config.ru 🔗

@@ -10,8 +10,9 @@ REDIS = Redis.new
 BRAINTREE_CONFIG = Dhall.load("env:BRAINTREE_CONFIG").sync
 
 class CreditCardGateway
-	def initialize(jid)
+	def initialize(jid, customer_id=nil)
 		@jid = jid
+		@customer_id = customer_id
 
 		@gateway = Braintree::Gateway.new(
 			environment: BRAINTREE_CONFIG[:environment].to_s,
@@ -21,9 +22,17 @@ class CreditCardGateway
 		)
 	end
 
+	def check_customer_id(cid)
+		return cid unless ENV["RACK_ENV"] == "production"
+
+		raise "customer_id does not match" unless @customer_id == cid
+
+		cid
+	end
+
 	def customer_id
 		customer_id = REDIS.get(redis_key)
-		return customer_id if customer_id
+		return customer_id if check_customer_id(customer_id)
 
 		cresult = @gateway.customer.create
 		raise "Braintree customer create failed" unless cresult.success?
@@ -62,13 +71,17 @@ class JmpPay < Roda
 	route do |r|
 		r.on :jid do |jid|
 			r.on "credit_cards" do
-				gateway = CreditCardGateway.new(jid)
+				gateway = CreditCardGateway.new(
+					jid,
+					request.params["customer_id"]
+				)
 
 				r.get do
 					view(
 						"credit_cards",
 						locals: {
-							token: gateway.client_token
+							token: gateway.client_token,
+							customer_id: gateway.customer_id
 						}
 					)
 				end

views/credit_cards.slim 🔗

@@ -16,6 +16,7 @@ form method="post" action=""
 	#braintree
 		| Unfortunately, our credit card processor requires JavaScript.
 
+	input type="hidden" name="customer_id" value=customer_id
 	input type="hidden" name="braintree_nonce"
 
 script src="https://js.braintreegateway.com/web/dropin/1.26.0/js/dropin.min.js"