Hacker News new | ask | show | jobs
by dcow 396 days ago
> Signing requests does give extra security points, but why do we collectively place higher security requirements on webhook requests than API requests?

TFA is exploring the juxtaposition of signed web-hook requests vs bearer token api requests, both of which provide authentication but one of which is arguably superior and in common enough use to question why it hasn't become common practice at large.

To flip the question: if there aren’t meaningful benefits to signing requests, why don’t web-hooks just use bearer token authentication?

5 comments

Both are http requests from client to server. Servers are already authenticated through TLS. The difference is who takes the role of the client.

With API requests the customer takes the client role. The endpoint is the same, eg api.stripe.com. This means, an API key (shared secret) is the minimal config needed to avoid impersonation. You could sign with a private key too but it would also require configuration (uploading the public key to stripe) so there’s not much security gained.

With webhooks, the vendor is the client and needs to authenticate itself. But since it’s always the same vendor, no shared secret is needed. They can sign it with the same private key for all customers. You can bake the public key into client libraries and avoid the extra config. Thus, it’s reasonable to believe the use of public key cryptography is not because it’s more secure, but simply more convenient. Signing is kind of beautiful for these types of problems.

Signing alone creates a potential security issue (confused deputy? Not sure if it has a name): if Eve creates a stripe account and tells stripe that her webhook lives on alice.example.com, ie Alice’s server, stripe could send real verified webhook events to Alice, and if she doesn’t check which account it belongs to, she might provision resources (eg product purchases) if Eve is able to replicate the product ids etc that Alice uses.

Edit: now that I think of it, eve doesn’t even need to point stripe to Alice’s server. She can just store and replay the same signed messages from stripe and directly attack Alice’s server, since the HTTPS connections are not authenticated (only the contents are). To mitigate, the client library should contain some account id in the configuration, in order to correctly discard messages intended for someone else.

It’s worth pointing out that Stripe, specifically, generates a per-endpoint secret for webhooks that is used for validating the signature.
I suspected as much. It would have been too obvious of an attack vector for something so sensitive. Then obviously my argument falls apart, since it’s no longer saves any config.

That said, you can still benefit from pub keys by having good infra and key rotations to prevent some attacks like message replay after months. Putting such a requirement on customers is pretty doomed because of the workload, processes and infra required.

Because then the client would need to host token vending infrastructure just to accept a webhook request.

As designed, the webhook receiver only has to implement the one endpoint.

[edit: in addition, bearer tokens are not the only authentication system. By moving authentication onto the webhook holder, the caller now has to satisfy any authentication system and have implementations for all of them. Some authentication systems are manual and thereby introduce friction. By providing the authentication materials themselves, they reduce friction and reduce their implementation to having only one mechanism.]

Some do, but it either involves an additional secret specific for this purpose, or it burdens the client with controlling access and exposure of incoming request headers (in logs and middleware) since they would include the token that can actually make api calls to the vendor.

Nevertheless, your question would have yielded a better article.

> but why do we collectively place higher security requirements on webhook requests than API requests?

We really don’t, signing is just more convenient in the webhook scenario. And it’s also completely optional to check a signature, leading even to many implementations not doing so.

Well put. I assume this is because big players make things as easy as possible to consume. APIs are probably more widely used that web hooks, so made easier for consumers to work with.
Some do; Gitlab, Otka, and Pipedrive come to mind. I think this is more about the expectations set over the last decade. If you do things differently, there's a need to justify it, and it's just perceived as less secure, regardless of whether it's true or not (the pros and cons are well articulated in the article).