Check Stripe Webhook Endpoint Signatures
As of today, a call can be made to the IPN url posting information about a given payment to attempt completing it. But there is an easy way to increase security by checking Stripe keys.
Stripe can optionally sign the webhook events it sends to your endpoints by including a signature in each event’s Stripe-Signature header. This allows you to verify that the events were sent by Stripe, not by a third party.
Source: Verify the events that Stripe sends to your webhook endpoints
How To Implement It
Actually, the Stripe PHP library already includes Stripe public keys, so in principle, the roadmap would be:
- Store the webhook secret as a payment processor paramenter
The Stripe API returns a secret
when a webhook endpoint is created but only during its creation:
The endpoint’s secret, used to generate webhook signatures. Only returned at creation.
Source: The webhook endpoint object
This means that when the webhooks are registered by the extension itself, we could automatically configure the webhook endoint secret and therefore activate checking the signature.
If the webhook isn't registered by the extension, it could still be as easy as adding the endpoint secret to the payment processor settings.
- Add at a call like this one at the beginning of the IPN main method
// Set $endpoint_secret (whsec_...) from the payment processor
$endpoint_secret = $this->getEndpointSecret($paymentProcessorID);
// Check the signature
try {
$event = \Stripe\Webhook::constructEvent(
@file_get_contents('php://input'),
$_SERVER['HTTP_STRIPE_SIGNATURE'],
$endpoint_secret
);
} catch(\Stripe\Exception\SignatureVerificationException $e) {
$this->exception('Invalid Stripe signature');
}
Benefits
A part from the obvious security improvement, checking signatures would also allow us trusting the information that comes with every Stripe event and, therefore, we could apply policies such as creating missing data entities where we are currently throwing exceptions (for instance: no [contribution |payment | subscription] found, etc).