Webhook - Identifying webhooks by id to match their secrets

I’m a bit confused at how to validate webhooks with their secrets.

Each time you create a webhook, you have an initial handshake where you receive a Secret from Asana. You’re supposed to store this secret so you can verify future signatures from event requests and confirm it’s coming from Asana.

For each webhook you create (eg. different projects, tasks, etc), you receive a different Secret. This means the validation for each event depends on the webhook it came from.

However, when an event is sent to my endpoint, the webhook’s gid (or any id at all) isn’t sent. It’s just the event data of things that changed/got deleted/etc.

If I have no way to identify which webhook this event got sent from, how can I know which Secret I need to use to validate the signature?

Eg:

  • I create Webhook A.
  • I store Secret A.
  • I create Webhook B.
  • I store Secret B.
  • I receive an event.
  • Do I use Secret A or Secret B to validate that event’s signature?
    Imagine that example but with hundreds of webhooks.

I hope someone can help me understand how to do this. Thanks!

1 Like

Hi @FrancoMuniz!

Yes, every webhook registered will have a unique X-Hook-Secret that is sent in the intial “handshake.” I would recommend that you use a unique target URI for every webhook you need to register. For example, if you’re using Node.js + Express to build your application for receiving webhook events, you can register a route that accepts a parameter.

app.post( "/webhooks/:id", async ( req, res ) => {
  const id = req.params.id;
  // use the id to store/retrieve the secret and any other relevant information
  // needed for this webhook registration
} );

With a route handler like this one, you can register as many webhooks as you need. Other web frameworks/languages have an equivalent way to create one route handler that can handle any number of URIs.

When you register a new webhook using POST https://app.asana.com/api/1.0/webhooks, the data you post to the endpoint might look something like the following.

{
  "data": {
    "resource": "12345678",
    "target": "https://myserver.com/webhooks/12345678"
  }
}

Let me know if this makes sense!

2 Likes

Another thing you can do is to use one target URI but include a unique payload as part of your webhook; you do this by adding extra URL query parameters in your target property. Those parameters get returned in the webhook from Asana so you can use those to identify which webhook it is. For example, his could be your target string:

target = "https://mywebapplication.com/api/webhook&myId=" + myUniqueId + "&type=project"

3 Likes

I up using a setup that combines the webhook daat with some identifiers

Like the webhook URL or specific headers, to match the event to its respective secret. This helped me narrow down which secret to use for validation. But I also recently came across an Identity Verification API that helps automate some of this kind of identification work, which could be useful in a case like this. You can find more about it at idanalyzer.com. I think it’s worth checking out if you’re dealing with a lot of webhooks and need something to help match events to their secrets.