From Stripe's webhooks documentation:
If security is a concern, or if it's important to confirm that Stripe sent the webhook, you should only use the ID sent in your webhook and should request the remaining details from the Stripe API directly.
Question
My ruby-on-rails application uses stripe for card payments. Stripe has a provision of webhooks through which it contacts back to my application and gives details about every transactions - succeeded or failed.
For this, I have in my controller something like this:
class StripeController < ApplicationController
def webhook
data_json = JSON.parse request.body.read
p data_json['data']['object']['customer']
end
My question is how can I validate the authenticity of this webhook? To my knowledge and understanding one can easily imitate this (man-in-the-middle attack).
Solution
From Stripe's webhooks documentation:
If security is a concern, or if it's important to confirm that Stripe sent the webhook, you should only use the ID sent in your webhook and should request the remaining details from the Stripe API directly.
OTHER TIPS
The gem stripe_event
has it covered in a different way.
Securing your webhook endpoint is done through Basic HTTP Authentication in stripe_event
gem.
If only Stripe knows the basic authentication password, this ensures that the request really comes from Stripe. Here's what you do:
Arrange for a secret key to be available in your application's environment variables or secrets.yml file.
Configure StripeEvent to require that secret be used as a basic authentication password, using code along the lines:
StripeEvent.authentication_secret = ENV['STRIPE_WEBHOOK_SECRET']
When you specify your webhook's URL in Stripe's settings, include the secret as a password in the URL, along with any username:
https://stripe:my-secret-key@myapplication.com/my-webhook-path
This is only truly secure if your webhook endpoint is accessed over SSL, which Stripe strongly recommends anyway.
You can enable basic http authentication
for the stripe webhook events by setting the webhook to the following url
https://username:password@myapplication.com/my-webhook-path
This will result in a Authorization
header with the value of
Basic encode64(username:password)
for instance by setting the webhook to the following url
https://admin:123456@myapplication.com/my-webhook-path
you will get this header in the inbound request
Basic YWRtaW46MTIzNDU2