Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

I'm new to webhooks - I understand them conceptually, but is there a standard for authenticating the incoming notification? Take the Stripe example - how do you know that the HTTP POST is actually coming from Stripe? Do you use a shared-secret, or some other mechanism to verify the HTTP request is authentic?


With Stripe, the process is:

1) Receive a webhook and record the ID in your database. If it's a duplicate, stop.

2) Ask Stripe for the event matching the ID they gave you. If they reject it, stop.

3) Process the event.

It requires a roundtrip, but it's the only sane way to validate that the event you got is real and that you haven't seen it before without trying to validate a signature (lots of other APIs make you do that, though)


Yes! This is the only part of Stripe's API that I raised an eyebrow at. I think it's a little irresponsible to send all the data via web-hook without providing a way to verify it came from Stripe.

At the very least they should only provide the event ID over webhook otherwise people will take the lazy route and trust trivially forgeable messages.


> I think it's a little irresponsible to send all the data via web-hook without providing a way to verify it came from Stripe.

Well, as zrail said, you can trivially verify it by fetching the associated event from Stripe and ignoring the webhook body.

We've debated this ourselves, though. While you can theoretically get good security with a combination of SSL and a shared secret in the URL, it's a bit ungainly, and we should perhaps encourage the right thing more straightforwardly by dropping the body from the POST.


You can trivially verify it by doing more work (a web request to Stripe) or you could just take the lazy route and trust the data that came with the callback.

I did it the way zrail suggested but laziness typically wins especially if you aren't even aware of the reasons you might want to do it the way zrail suggested.

I'm for making the right way the only way (or at least the default way).


Great question!

For Iron.io, all our requests are authenticated using an OAuth token. So only people that know your OAuth token (and thus could use our API anyways) can use your webhook endpoints.

But there are other ways, too. The most common I've seen is to provide an API endpoint to verify events with (Stripe does this). If you use HTTPS to receive the webhook, and verify it with a request over HTTPS to the API you expect it to be coming from, you're ensuring the request is authentic.

For some webhook styles, it doesn't actually matter. Some people use webhooks to just say "Something happened", without actually saying what. In this style, the API is still responsible for the data and authentication, the webhook just says "Hey, wake up, the API has something new for you."


Got it. Thanks for the initial write-up, and your explanation.


There isn't a standard way of authenticating the incoming notification yet. I like how Mailgun is doing it, to verify the webhook is originating from Mailgun you need to:

  * Concatenate timestamp and token values.
  * Encode the resulting string with the HMAC algorithm (using your API Key as a key and SHA256 digest mode).
  * Compare the resulting hexdigest to the signature.
  * Optionally, you can check if the timestamp is not too far from the current time.
So, you essentially get 3 extra parameters from your webhook, `timestamp`, `token` and `signature`. Obviously, the API key is the shared secret here between your app and Mailgun.


Grooveshark does it as well.

http://developers.grooveshark.com/docs/public_api/v3/

However it depends on a shared secret for generating/verifying signatures, and some companies (cough Stripe cough) have yet to implement that. As someone else has already mentioned, thankfully each webhook request from Stripe has an ID in it so you can query their API for verifying a webhook's authenticity.


If it's just a shared secret, why not just make a secret (and complicated) URL for the web hook? It's shared with the deliverer but as long as you're using SSL it should be just as secure.

Speaking of which, the right way to do this is to validate their SSL client certificate, but I doubt many places are easily setup to do that - in fact I would bet the sending endpoint doesn't even use a certificate most of the time.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: