There’s a couple of things I haven’t been able to find any documentation on:
Is there any way during the webhook establishment to get the API asana to use an authentication token when repeating back the x-hook-secret? I suppose I can set a domain level filter for the response and then rely on the x-hook-secret to maintain a secure connection but I would rather have the API return an authentication token at least during the initial handshake
How often do handshake secrets rotate? In the above case that I cannot secure the transmission from Asana to my API, if the handshake secret rotates frequently then I would have to manually monitor the handshake creation each time to ensure traffic is secure.
Apologies for the late reply. To answer your question
Is there any way during the webhook establishment to get the API asana to use an authentication token when repeating back the x-hook-secret? I suppose I can set a domain level filter for the response and then rely on the x-hook-secret to maintain a secure connection but I would rather have the API return an authentication token at least during the initial handshake
Our API does not return an authentication token or support sending one along with the x-hook-secret. It would be best to rely on the x-hook-secret for a secure connection.
How often do handshake secrets rotate? In the above case that I cannot secure the transmission from Asana to my API, if the handshake secret rotates frequently then I would have to manually monitor the handshake creation each time to ensure traffic is secure.
The x-hook-secret does not rotate it’s meant to be stored and used to generate a computed signature with the event body to validate the x-hook-signature. So each time you get a webhook event it’ll come with an x-hook-signature that you are supposed to verify. This x-hook-signature is most likely different for each event since it’s computed using the x-hook-secret and event body. See the our Receiving events doc for more details.
Also, we recently introduced an AI chatbot in our developer docs. Feel free to ask it questions. I asked it your questions and the answer it gave aligns with what I’ve said.
For number 1. this means we would have to expose an API for the initial handshake (i.e we send out a request to establish the webhook, but we receive the secret for the first time). So we would have a fully exposed API for that initial handshake but then it would be secured by the secret. I asked your LLM chatbout about whitelisting your IP ranges but it said I need to contact support. Understood that after the initial handshake we’re relatively secure (we check the x-hook-secret against the one were sent and anything that doesn’t have it or doesn’t match we throw out) but this setup is unsecure unless we whitelist the incoming IP ranges for the webhook secret response.
If we cannot setup a whitelist on our side for the initial handshake, spinning up new webhooks is going to be a manual process. We’ll have to monitor requests while doing it, make sure that only the ones we expect come in and then be fine.
Thanks for the details @Harrison_Reid. I can see why you are concerned. I don’t have a solution in mind at the moment, but I can ask around to see if others have ideas/recommendations on securing the initial handshake. We use AWS lambda functions for our webhooks. If you would like to do whitelisting you can see the range of addresses in the AWS docs AWS IP address ranges - Amazon Virtual Private Cloud. Whitelisting the range of IP addresses isn’t the most ideal but it’s better than allowing any IP address.
Hi @Harrison_Reid, I talked to our engineer and Solutions team and they have a few recommendations on making the initial handshake more secure. Here are some things you can do:
Minimizing the attack surface:
Your webhook server should only listen for and respond to a handshake request during the period when they have an outbound request to Asana to set a webhook (Establish a webhook ). This won’t eliminate the attack of someone trying to setup a fake webhook handshake during that time window, but significantly limits the surface area.
Using Target URL query params (similar to your idea for #1)
On your webhook server generate a one-time code for webhook setup
Pass in your one-time code in the URL parameters for the target when you make a call to Establish a webhook
Asana will make a call to your target URL that will contain your one-time code along with the x-hook-secret during the initial handshake
Your app server reads the one-time code and checks that it’s the one you sent