I’ve been working on debugging this one for a couple weeks now. Due to the fact that this project is not open source, and there is encryption being employed to verify requests, it took a while indeed to finally figure out where this bug was exactly. I have been circling it for a couple weeks, but I didn’t have the time to go all the way down the rabbit hole until now.
The Workwave API functions by having the client set a callback url where Workwave can send requests when deliveries and other things occur in Workwave. This callback url must conform to best practices for urls, and therefore cannot violate the RFC’s for urls by, for example, having a non-url-encoded space in the url.
The Acumatica Webhook feature, on the other hand, does not url encode spaces in webhook urls, and hardcodes the url for a webhook to the name of the site and the company, which can have a non-url encoded space in it...see red arrow.
This is where we get into the catch 22 part of this particular bug. If you add %20 to the Acumatica webhook url, and store it with Workwave, it will be accepted, and Workwave will properly make a callback to the Acumatica webhook. If you do not add %20 to the Acumatica webhook url, Workwave will fail to store the url at all and callbacks will not work. So we have to url encode the space for our webhook to be stored by Workwave.
This then leads to a problem in the Acumatica webhook. The bug starts in the “Authenticate” method of Acumatica.Workwave.Webhook.WWCallbackAuthenticator.
In this method, there is a call to WWCallbackAuthenticator.RemoveParameterFromUrl…. and when the url is returned from this method, the escaping of spaces is removed. So now, even if we added the %20 to our url to store it with Workwave, it is now removed.
Then, the url with the non-url-encoded space, is used in the function to verify whether the signed message came from the correct url. However, since the urls are no longer exactly the same (%20 removed), the hashing does not return the same signature, and the function returns false.
Worse, this webhook is programmed to simply return 400 bad request when the callback does not authenticate, so we get no information about why the webhook failed (the url signature does not match the one returned by Workwave).
I have confirmed that if we provide the correct signature in debug, then the webhook returns HTTP 200 and everything is cool. Also, Workwave will not store the callback url if HTTP 200 is not returned on the first attempt (per Workwave API docs), so this will prevent Workwave callbacks from being registered by Acumatica at all.
There is some other stuff in here that seems very inefficient (looping through all url get parameters when we already know which ones we want to extract), etc. So I think this project could use the eyes of a senior engineer to clean it up and make it work better.
Also, please work with Workwave to discuss potentially open sourcing parts of this project. I think it will make a lot more progress as an open source project where we can freely share/discuss the code. This is communication between two open apis, so I’m not sure what is being protected here.
Best answer by rosenjonView original