The first thing that pops out to me is that there might be a bug in the logic, at least as presented. It reads to me as “If the header is not set, then set it to some arbitrary string, then return it”.
The thing to do here is to pull the value out of the header (it should always be there for the handshake and never there for subsequent webhook responses), then return the value you pulled out to us just as it is. It doesn’t look like you’re actually doing that here, at least not by what you’ve included in the question.
It looks to me like you might benefit from checking out some of our examples, which we’re working on building out (we’re planning on publicizing them a bit more as they get more feature rich and documented). Here’s the section of the code that does this in our example: https://github.com/Asana/devrel-examples/blob/master/python/webhooks/webhook_inspector.py#L144
At that point, if you echo back the webhook exactly, your handshake should succeed and you should start getting webhooks.
Also worth noting is why this header exists. It’s optional but recommended for you to use; you can get webhooks without it. It’s a security precaution you can take on your end: you have a server up and running that can take incoming requests from just about anywhere. How do you know that there’s not an attacker out there spoofing the sort of requests that Asana might be sending you? Webhooks don’t have any inbound authentication; that is, Asana doesn’t have to log in or send an auth token to your server to prove it’s Asana.
That’s the general purpose of the X-Hook-Secret: it’s more or less a random token that Asana stores on our side; then when we respond with webhook events, we calculate a signature in a way that can only be done if we know the secret. You can also calculate this signature client-side (this is optional, but recommended) and if the signatures match, you know it’s Asana.
This is secure because the only way for us to create and store the secret is when you request us to - when you first create the webhook. That’s why the secret is used for the handshake (and why it’s called a handshake, which is a common term in security for exchanging secrets).
- You authenticate with Asana to create the webhook, so Asana knows it’s you
- We send you a secret in another request, which you are expecting, since you asked Asana for it with the webhook creation request. You can then store this secret, and we share it on Asana’s side and on your client.
- When a future incoming request comes, if the same secret we share calculates the same signature on both sides, then you know that the webhook event is really from Asana.
If you look in that example, you can see that we demonstrate this as well. https://github.com/Asana/devrel-examples/blob/master/python/webhooks/webhook_inspector.py#L153