README.md in stripe_event-1.4.0 vs README.md in stripe_event-1.5.0

- old
+ new

@@ -1,7 +1,7 @@ # StripeEvent -[![Build Status](https://secure.travis-ci.org/integrallis/stripe_event.png?branch=master)](http://travis-ci.org/integrallis/stripe_event) [![Dependency Status](https://gemnasium.com/integrallis/stripe_event.png)](https://gemnasium.com/integrallis/stripe_event) [![Gem Version](https://badge.fury.io/rb/stripe_event.png)](http://badge.fury.io/rb/stripe_event) [![Code Climate](https://codeclimate.com/github/integrallis/stripe_event.png)](https://codeclimate.com/github/integrallis/stripe_event) [![Coverage Status](https://coveralls.io/repos/integrallis/stripe_event/badge.png)](https://coveralls.io/r/integrallis/stripe_event) +[![Build Status](https://secure.travis-ci.org/integrallis/stripe_event.svg)](http://travis-ci.org/integrallis/stripe_event) [![Dependency Status](https://gemnasium.com/integrallis/stripe_event.svg)](https://gemnasium.com/integrallis/stripe_event) [![Gem Version](https://badge.fury.io/rb/stripe_event.svg)](http://badge.fury.io/rb/stripe_event) [![Code Climate](https://codeclimate.com/github/integrallis/stripe_event.svg)](https://codeclimate.com/github/integrallis/stripe_event) [![Coverage Status](https://coveralls.io/repos/integrallis/stripe_event/badge.svg)](https://coveralls.io/r/integrallis/stripe_event) StripeEvent is built on the [ActiveSupport::Notifications API](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html). Incoming webhook requests are authenticated by [retrieving the event object](https://stripe.com/docs/api?lang=ruby#retrieve_event) from Stripe. Define subscribers to handle specific event types. Subscribers can be a block or an object that responds to `#call`. ## Install @@ -10,11 +10,11 @@ gem 'stripe_event' ``` ```ruby # config/routes.rb -mount StripeEvent::Engine => '/my-chosen-path' # provide a custom path +mount StripeEvent::Engine, at: '/my-chosen-path' # provide a custom path ``` ## Usage ```ruby @@ -68,10 +68,33 @@ StripeEvent.subscribe 'customer.card.' do |event| # Will be triggered for any customer.card.* events end ``` +## Securing your webhook endpoint + +StripeEvent automatically fetches events from Stripe to ensure they haven't been forged. However, that doesn't prevent an attacker who knows your endpoint name and an event's ID from forcing your server to process a legitimate event twice. If that event triggers some useful action, like generating a license key or enabling a delinquent account, you could end up giving something the attacker is supposed to pay for away for free. + +To prevent this, StripeEvent supports using HTTP Basic authentication on your webhook endpoint. If only Stripe knows the basic authentication password, this ensures that the request really comes from Stripe. Here's what you do: + +1. Arrange for a secret key to be available in your application's environment variables or `secrets.yml` file. You can generate a suitable secret with the `rake secret` command. (Remember, the `secrets.yml` file shouldn't contain production secrets directly; it should use ERB to include them.) + +2. Configure StripeEvent to require that secret be used as a basic authentication password, using code along the lines of these examples: + + ```ruby + # STRIPE_WEBHOOK_SECRET environment variable + StripeEvent.authentication_secret = ENV['STRIPE_WEBHOOK_SECRET'] + # stripe_webhook_secret key in secrets.yml file + StripeEvent.authentication_secret = Rails.application.secrets.stripe_webhook_secret + ``` + +3. 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. + ## Configuration If you have built an application that has multiple Stripe accounts--say, each of your customers has their own--you may want to define your own way of retrieving events from Stripe (e.g. perhaps you want to use the [user_id parameter](https://stripe.com/docs/apps/getting-started#webhooks) from the top level to detect the customer for the event, then grab their specific API key). You can do this: ```ruby @@ -167,8 +190,16 @@ ### Note: 'Test Webhooks' Button on Stripe Dashboard This button sends an example event to your webhook urls, including an `id` of `evt_00000000000000`. To confirm that Stripe sent the webhook, StripeEvent attempts to retrieve the event details from Stripe using the given `id`. In this case the event does not exist and StripeEvent responds with `401 Unauthorized`. Instead of using the 'Test Webhooks' button, trigger webhooks by using the Stripe API or Dashboard to create test payments, customers, etc. +### Maintainers + +* [Ryan McGeary](https://github.com/rmm5t) +* [Pete Keen](https://github.com/peterkeen) +* [Danny Whalen](https://github.com/invisiblefunnel) + +Special thanks to all the [contributors](https://github.com/integrallis/stripe_event/graphs/contributors). + ### License -[MIT License](https://github.com/integrallis/stripe_event/blob/master/LICENSE.md). Copyright 2012-2014 Integrallis Software. +[MIT License](https://github.com/integrallis/stripe_event/blob/master/LICENSE.md). Copyright 2012-2015 Integrallis Software.