I’m looking to set up a webhook and I believe the approach being used for the HMAC calculation is incorrect.
The approach as follows:
- create webhook using POST from client to Asana API.
- Asana API POSTs to the webhook endpoint with X-Hook-Secret for the handshake.
- webhook endpoint responds with HTTP 200 and the X-Hook-Secret in the header.
- Asana API responds to the initiating client with no X-Hook-Secret, but only the Gid of the webhook created.
According to the documentation linked from Asana site, http://resthooks.org/docs/security/
To ensure that a Receiver actually intends to receive hooks from a Sender, a subscription uses a temporary secret in the initial handshake.
Now an event happens, sent to the webhook. It has X-Hook-Signature, which is a HMAC-256 of the event body and the temporary X-Hook-Secret from the handshake. This means that the X-Hook-Secret from the handshake needs to be persisted on the client end, for each webhook created.
I think the document is inferring later, that the HMAC should be using the API secret, not the temporary secret:
To prove the authenticity of subsequent messages, the Sender can use a shared secret (think API key or OAuth client_secret).
This, of course, is much easier to store encrypted and use for each incoming request, rather than having a separate secret for each incoming request.
Love to hear your feedback and if this is in fact working as designed, and what the best way is to handle this. I would prefer to confirm the validity of the webhook events but this is a seemingly large overhead to have to store a separate secret for each webhook created.