Solved

Workwave integration is bugged for Companies with spaces in their names

  • 9 August 2022
  • 5 replies
  • 186 views

Userlevel 6
Badge +5

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.

Thanks,

Jonathan

icon

Best answer by rosenjon 17 August 2022, 07:46

View original

5 replies

Userlevel 7
Badge +10

 

@rosenjon we have faced similar issues with tenants that have special characters as well in other integrations we have built at Velixo. Some of those issues have been fixed already, but I would suggest opening a support ticket on portal.acumatica.com to ensure this gets routed to the proper team -- no guarantee someone from the integrations team will see this here.

 

Userlevel 6
Badge +5

Thanks @Gabriel Michaud . I’m not offiicially an Acumatica customer yet, so I don’t think I have access to that portal. But perhaps someone else can post there with a link to this discussion forum post. I was thinking I might also make a post on StackOverflow, where it seems there are some Acumatica devs hanging out sometimes.

Maybe the easiest way to fix this problem long term would be to have a “tenant url name” field, which enforces best practices for url schemas? So when you go to create a tenant, it would automatically strip all spaces etc from the name, and populate the “tenant url name” field with a url-safe tenant name. This would tradeoff allowing for custom naming in the url with enforcing best practices as well. The tenant url name could also be editable as long as url naming best practices are followed.

 

 

Userlevel 7
Badge +2

Hi @rosenjon, i will make sure this gets discussed here at Acumatica, no need to post on StackOverflow.

-thanks, Dana

Userlevel 6
Badge +5

Thanks @Dana Moffat.

For comapnies like ours, that run our own trucks (in addition to third party shippers, UPS, etc), this Workwave integration is a really cool idea. I think distinguishing between drop-off only and pickup would be a good next step for this integration, so that those things aren’t tied together by definition. The current setup is confusing for a driver if it tells him to make a pickup at a stop but he is only ever dropping off.

Userlevel 6
Badge +5

Here is a patch for this problem. This simplifies the code quite a bit while also handling url encoding issues. The unpatched version of this has a loop over the this.plugins variable, which iterates more than once and causes issues with the authentication function returning more than once.

At the end of the day, we just need to make sure that the signature passed with the request validates against the stored signature key, which is relatively simple to calculate (does not require a bunch calls to other classes/methods).

 

public bool Authenticate(Uri requestUri)
{
KeyValuePair<string, string> keyValuePair = this.plugins[0];
string leftPart = requestUri.GetLeftPart(UriPartial.Path);
NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(requestUri.Query);
string b = nameValueCollection.Get("signature");
nameValueCollection.Remove("signature");
string message = leftPart + "?" + nameValueCollection.ToString();
string a = this.CreateToken(message, keyValuePair.Value);
bool result = false;
if (a == b)
{
result = true;
}
return result;
}

 

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved