Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why a message signature instead of using the Authorization header? #110

Open
reda-alaoui opened this issue Feb 1, 2024 · 3 comments
Open

Comments

@reda-alaoui
Copy link

This is a question I have always asked myself regarding webhooks.

Why not let the sender pass a token (originally crafted by the receiver) via the Authorization header?

@zekth
Copy link
Member

zekth commented Feb 21, 2024

Because an Authorization header protects the AuthN part of a path / route ; the signature protects the handling of the message itself. Basically this is 2 domain knowledge difference; one can happen at the gateway/router level and the other one at the processing of the message.

@reda-alaoui
Copy link
Author

@zekth I think I am aware of that difference.
But why is that needed for webhooks while there is no literature about this in a classic client to server http communication?

Why do I need to sign the message when I have webhook event creator ----http-message----> webhook event consumer while it's not usual to sign the message when I have http client ----http-message----> http server ? Or the message should be signed in both cases?

@tasn
Copy link
Contributor

tasn commented Feb 21, 2024

@reda-alaoui, there are two questions here: the first whether to use the Authorization header, and the second, maybe to use a token (rather than a signature) - but not in the Authorization header.
For the first question: I believe @zekth answered it. In most systems the Authorization is handled in a way where you can't really give it a "webhook" access level. Whether it's because the authentication is done in the API Gateway layer or even in a framework. Giving a "real" token can be a source for trouble if even possible.
As for the second question: why not just pass a token in a Webhook-Token header? There are a few reasons (I've been meaning to do a proper write-up on the topic). The first is that signatures are better than tokens in general, and is why some APIs (e.g. the AWS API) are using signatures rather than tokens. The advantage of signatures is that they are less likely to leak than a token because they are not sent on the wire so can't, e.g. be logged. This is especially important with webhooks where it can be common to e.g. put the wrong url so put example1.com instead of example2.com which means you'd have the token sent to another server not controlled by you, which means the token will be compromised. Not the case with signature. Sure, you can automatically revoke token when changing the URL but that's a pain because people may have legitimate reasons to change just part of the URL (e.g. query params), and it's in general just a pain. There are also other reasons why you can, with webhooks, more easily send webhooks to places where they weren't intended so this is a good thing. So another question comes up: why sign the payload? Why not just sign a random key and then have the user verify that? That would actually be a big improvement over tokens (for APIs too tbh), but if you're already doing signatures why not get the benefits of signing the payloads?
Benefits of signing the payloads: no MITM potential (e.g. an attacker can get the wrong URL set potentially, have it sent to them, and then modify and forward to you) which is a big win. This also protects against replay attacks because you also sign the timestamp and the idempotency key. The last advantage of a signed payload which is more relevant to webhooks than an API call: non-repudiation. You know that if you get the webhook it most have come from the source (taking all of the above comments in mind) which means you can prove it's authentic in case of conflict. So if e.g. Stripe sends you a webhook it comes with an extra layer of authenticity. This is somehow relevant with symmetric signatures (as you can potential sign things yourself as you have the key), but super relevant with asymmetric where only Stripe would have the key.

This was a bit of a brain dump so it may not be super clear. I've been meaning to do a better write up but haven't gotten to it yet. Feel free to ask follow up questions if you have any!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants