Why do webhooks use secrets? Why not use just SSL?

Viewed 81

Standard practice is for an event-notification-service to give you a secret when you register your endpoint with them, and then the service signs the messages it sends to your endpoint with that shared secret, so that your server can verify the messages are legitimate.

However why is this necessary? Assuming your endpoint and the event-notification-service are both using HTTPS, shouldn't HTTPS take care of everything you need anyway, making this entire secret and signing process redundant? Is the idea to not rely on SSL-certificates, or allow clients to use endpoints that are not HTTPS?

1 Answers

The signing secret is here to ensure the event does come from Stripe. The signature is also associated with a specific timestamp to avoid "replay attacks".

Without the secret, I could figure out or guess the webhook handler that you built that expects for example the checkout.session.completed event and then I would send you a fake event evt_123 making it look like the payment succeeded for you to give me access to the product for example. There are some ways around this (hard to guess endpoint, allow list for Stripe's IP addresses, secret in the URL, etc.) but they all have downsides.

Similarly, if I can find the payload of an event that works, I could re-use the same exact payload (that I know is valid since you accepted it) and replay it say every day to continue getting daily access to some content. With the webhook signature logic that Stripe built, the signature is associated to a specific timestamp and you can for example reject events if the signature is more than 10 minutes old. Stripe covers this in their docs here.

Related