I would be creating Stripe web hooks and want to know how to ensure security such that only Stripe can access my URL?
I am using Laravel with the Stripe library.
I would be creating Stripe web hooks and want to know how to ensure security such that only Stripe can access my URL?
I am using Laravel with the Stripe library.
As noted in the 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. We also advise you to guard against replay-attacks by recording which events you receive, and never processing events twice.
In other words, there's no way to confirm where a request came from. As such, don't trust any of its data, except for the id of any given item. You then contact the Stripe API yourself, asking for the item with the given id. This way you know where you're getting your data from, and the webhook call essentially just becomes a notification letting you know you should check in with the API.
Actually you can limit the access to your webhooks only to the Stripe IPs. That's why Stripe have a list of webhooks ips updated.
I just did it for a project using Laravel and Stripe. You can do something like:
//Only accept connections from stripe ips.
//Save stripe info for 24 hours for performance.
$stripe_webhooks_ips = Cache::remember('stripe_webhooks_ips', 1440, function()
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, 'https://stripe.com/files/ips/ips_webhooks.json');
$result = curl_exec($ch);
curl_close($ch);
$json_result = json_decode($result,true);
return $json_result['WEBHOOKS'];
});
if(in_array($_SERVER['REMOTE_ADDR'],$stripe_webhooks_ips)) {
//Your Code Here.
}
About the security of the remote_addr variable: Is it safe to trust $_SERVER['REMOTE_ADDR']?
Remember to take extra measures to get the origin ip if you are behind a proxy or a CDN service like Cloudfare, etc.
Stripe signs the events it sends to you, so you can validate the signature to check Stripe was the sender.
The Stripe libraries will handle this for you, including replay attack prevention. See the docs at https://stripe.com/docs/webhooks/signatures. There is a PHP example.
Idempotency is a separate matter. You could receive events more than once, which is your problem to deal with (by tracking event IDs). This is mentioned on this page: https://stripe.com/docs/webhooks/best-practices.
It has been previously mentioned but I you check check the signature of the requests with the webhook secret that stipe provides to you. The following example comes from Appwrite's function templates. You might check the source code of the validation function on GitHub.
validateWebhook(context, req) {
try {
const event = this.client.webhooks.constructEvent(
req.bodyRaw,
req.headers['stripe-signature'],
process.env.STRIPE_WEBHOOK_SECRET
);
return /** @type {import("stripe").Stripe.DiscriminatedEvent} */ (event);
} catch (err) {
context.error(err);
return null;
}
}
const event = stripe.validateWebhook(context, req);
if (!event) {
return res.json({ success: false }, 401);
}
© 2022 - 2024 — McMap. All rights reserved.