Phoenix
Phoenix

Reputation: 1075

Why Stripe's webhooks do not need verify signature?

Neither doc (https://stripe.com/docs/webhooks) nor SDK(stripe-php) uses any signature method. So I doubt, what if someone fake as official webhook sender?

In SDK, only retrieve event id successfully will consider a good webhook, I think it's too risky, isn't it?

Upvotes: 2

Views: 7799

Answers (3)

texelate
texelate

Reputation: 2498

There are two ways to do this. They have been covered already but I will consolidate everything into a single answer.

Option 1

Check the event is valid (throws an exception if not).

\Stripe\Event::retrieve($event_id)

Option 2

HMAC the Stripe-Signature header using the whsec* key found in your dashboard.

// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("sk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = "whsec_...";

$payload = @file_get_contents("php://input");
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;

try {
  $event = \Stripe\Webhook::constructEvent(
    $payload, $sig_header, $endpoint_secret
  );
} catch(\UnexpectedValueException $e) {
  // Invalid payload
  http_response_code(400); // PHP 5.4 or greater
  exit();
} catch(\Stripe\Error\SignatureVerification $e) {
  // Invalid signature
  http_response_code(400); // PHP 5.4 or greater
  exit();
}

// Do something with $event

http_response_code(200); // PHP 5.4 or greater

Code from https://stripe.com/docs/webhooks/signatures

Option 1 is simpler, requires an extra call to the API but option 2 requires you store an extra key in your application and requires for code (I prefer option 1). I checked with Stripe support today and they confirmed they are both as good as each other in terms of verifying the validity of an API call so it is a matter of choice.

Upvotes: 3

Edward
Edward

Reputation: 2359

Stripe does provide signatures for web hooks. Take a look here: https://stripe.com/docs/webhooks#signatures

You can also take a look at this article: https://www.truespotmedia.com/testing-webhooks-in-stripe-with-php/

Here is some example code:

// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("your secret api key");

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = "whsec_...";

$payload = @file_get_contents("php://input");
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;

try {
  $event = \Stripe\Webhook::constructEvent(
    $payload, $sig_header, $endpoint_secret
  );
} catch(\UnexpectedValueException $e) {
  // Invalid payload
  http_response_code(400); // PHP 5.4 or greater
  exit();
} catch(\Stripe\Error\SignatureVerification $e) {
  // Invalid signature
  http_response_code(400); // PHP 5.4 or greater
  exit();
}

// Do something with $event

http_response_code(200); // PHP 5.4 or greater

Upvotes: 5

Kisaragi
Kisaragi

Reputation: 2218

You can solve this by saving the event id and then retrieving the event from stripe to make sure the event is valid:

\Stripe\Event::retrieve($event_id)

Upvotes: 2

Related Questions