Unable to verify Forge callback payload signature

346 Views Asked by At

I am currently using Forge Webhooks API to handle different events that might occur on a project. Everything works fine, except the payload signature check.

The reason why I want to check the payload is because the callback will end up on my API and I want to reject all requests that do not come from Forge's webhook service.


Steps I followed:

  1. Add (register) secret key (token) on Forge. API Reference
  2. Trigger an event that will eventually call my API for handling it.
  3. Validating signature header. Followed this tutorial.
  4. PROBLEM!!! My computedSignature is different from the signature received from Forge.

My C# code looks like this:

private const string SHA_HASH = "sha1hash";

var secretKeyBytes = Encoding.UTF8.GetBytes(ForgeAuthConfiguration.AntiForgeryToken);

using var hmac = new HMACSHA1(secretKeyBytes);

var computedHash = hmac.ComputeHash(request.Body.ReadAsBytes());

var computedSignature = $"{SHA_HASH}={computedHash.Aggregate("", (s, e) => s + $"{e:x2}", s => s)}";

For one example, Forge's request has this signature header: sha1hash=303c4e7d2a94ccfa559560dc2421cee8496d2d83

My C# code computes this signature: sha1hash=3bb8d41c3c1cb6c9652745f5996b4e7f832ca8d5

The same AntiForgeryToken was sent to Forge at step 1

Ok, I thought my C# code is broken, then I tried this online HMAC generator and for the given input, result is: 3bb8d41c3c1cb6c9652745f5996b4e7f832ca8d5 (same as C#)

Ok, maybe the online generator is broken, I tried their own code in node js and this is the result:

enter image description here


I have 3 ways of encrypting the SAME body using the SAME key and I get the SAME result every time. BUT those results are DIFFERENT from the signature provided by Forge, resulting in failing the check and rejecting a valid request...

Does anyone know what is happening with that signature?

Why is it different from my result if I follow their tutorial?

How are you validating your requests?

2

There are 2 best solutions below

1
On

The code below is working at my side. Could you give it a try if it helps?

    [HttpPost]
    [Route("api/forge/callback/webhookbysig")]
    public async Task<IActionResult> WebhookCallbackBySig()
    {
        try
        {
            var encoding = Encoding.UTF8;
            byte[] rawBody = null;
            using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
            {
                rawBody = encoding.GetBytes(reader.ReadToEnd());
            }
            var requestSignature = Request.Headers["x-adsk-signature"];
            string myPrivateToken = Credentials.GetAppSetting("FORGE_WEBHOOK_PRIVATE_TOKEN");
            var tokenBytes = encoding.GetBytes(myPrivateToken);
            var hmacSha1 = new HMACSHA1(tokenBytes);
            byte[] hashmessage = hmacSha1.ComputeHash(rawBody);
            var calculatedSignature = "sha1hash=" + BitConverter.ToString(hashmessage).ToLower().Replace("-", "");
            if (requestSignature.Equals(calculatedSignature))
            {
                System.Diagnostics.Debug.Write("Same!");
            }
            else
            {
                System.Diagnostics.Debug.Write("diff!");
            }

        }
        catch(Exception ex)
        {

        }

        // ALWAYS return ok (200)

        return Ok();        
 }

If this does not help, please share with your webhook ID (better send email at [email protected]). We will ask engineer team to check it.

0
On

The way to check the signature is correct, I believe the issue is setting the secret token, did you correctly set the secret token for your App by endpoint https://aps.autodesk.com/en/docs/webhooks/v1/reference/http/tokens/tokens-POST/ ? Make sure to use the secret token to verify all the coming callback.