Validating WebHooks in C#

So, after a little work, I was able to validate web hooks using C#. Here is the method :).

HMACSHA256 hmac = new HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_dwollaOptions.WebHookSecret));

            Stream req = context.HttpContext.Request.Body;
            req.Seek(0, SeekOrigin.Begin);
            string json = new StreamReader(req).ReadToEnd();

            var validationHash = BitConverter.ToString(hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(json))).Replace("-", "").ToLower();

            if (context.HttpContext.Request.Headers["X-Request-Signature-Sha-256"].ToString() != validationHash)
            {
                context.Result = new UnauthorizedResult();
            }
1 Like

This is very helpful!

Thank you so much for sharing, @vincentbetro! :slight_smile:

1 Like

I tried this example, but it didn’t work in my case, request.Body - stream is empty on any request.
instead of BodyStream I tried to get payload using context.ActionArguments.TryGetValue("payload", out var readToJson); it gave me the payload but HMACSHA256 encrypted by Secret gives me the different hash from received from Dwolla.

public bool ValidateDwollaSignature(string sha256Hash, string jsonPayload)
		{
			var secret = Encoding.ASCII.GetBytes(_dwollaOptions.WebHookHandlerOption.Secret);

			using var sha256 = new HMACSHA256(secret);
			var inBytes = Encoding.ASCII.GetBytes(jsonPayload);
			var computedHash = sha256.ComputeHash(inBytes, 0, inBytes.Length);
			var hex = BitConverter.ToString(computedHash).Replace("-", string.Empty).ToLower();

			return sha256Hash.Equals(hex);
		}

So, you are using ASCII encoding instead of UTF8. Also, it is odd that you did not get a stream back from HttpContext.Request.Body, but as long as the json is the same, it should give the same result.

@shreya was super helpful when I was working on this, so I imagine she would also be able to help you!

I changed to UTF8 but the result is the same, I don’t understand what I am doing wrong.

It seems that you are doing everything correctly as far as parsing and comparing, but since you are unable to get the stream information from the Request body, you may not be getting the right information to compare with. You need to figure out how to get the request body back from the web hook response.