SHA256 webhook signature from WooCommerce never verifies

后端 未结 6 1000
再見小時候
再見小時候 2021-01-02 23:47

I am receiving webhooks from a woocommerce site into a nodejs/express application. I am trying to verify the webhook\'s signature to prove authenticity, yet the hash I compu

6条回答
  •  旧时难觅i
    2021-01-03 00:36

    I stumbled upon this while searching for a solution to have an Asp.NET application check signature of the Woocommerce web hook. My answer is based on the pseudo code Johannes provided which worked great. I implemented a custom controller attribute to intercept the request and check the signature before it hits the API controller method:

    public class HmacSignatureFilter : ActionFilterAttribute
    {
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var requestContent = actionContext.Request.Content;
            var jsonContent = requestContent.ReadAsStringAsync().Result;
            var byteContent = requestContent.ReadAsByteArrayAsync().Result;
    
            //if the request contains this, it's the verification request from Woocommerce
            //when the webhook is created so let it pass through so it can be verified
            if (!jsonContent.Contains("webhook_id"))
            {
                var requestSignature = actionContext.Request.Headers;
    
                var bodyHash = HashHMAC("test", byteContent); //this is the shared key between Woo and custom API.  should be from config or database table.
    
                var signature = actionContext.Request.Headers.GetValues("x-wc-webhook-signature");
    
                if (bodyHash != signature.FirstOrDefault())
                {
                    throw new HttpResponseException(HttpStatusCode.Forbidden);
                }
            }
    
            base.OnActionExecuting(actionContext);
        }
    
    
        private static string HashHMAC(string key, byte[] message)
        {
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var hash = new HMACSHA256(keyBytes);
    
            var computedHash = hash.ComputeHash(message);
            return Convert.ToBase64String(computedHash);
        }
    }
    

    Then to use the filter in your Api controller:

    [RoutePrefix("api/woo")]
    public class WooController : ApiController
    {
    
        public SomeService _service;
    
        public WooController()
        {
            this._service = new SomeService();
        }
    
        // POST api/values
        [Route("orderCreated")]
        [HttpPost]
        [HmacSignatureFilter]
        public string Post()
        {
            var requestContent = Request.Content;
            var jsonContent = requestContent.ReadAsStringAsync().Result;
    
            //this is the test request from Woocommerce.  Don't do anything but 
            //respond so it can verify the endpoint
            if (jsonContent.Contains("webhook_id"))
            {
                return "Webhook Test Success";
            }
    
            var wooOrder = JsonConvert.DeserializeObject(jsonContent);
    
            //call a service to use the order data provided by WooCommerce
            _service.AddOrder(wooOrder);
    
            return "Success";
        }
    
    }
    

    Note: Hashing code was referenced from this SO post.

提交回复
热议问题