11/18/2016

WooCommerce API Using RestSharp Over HTTP With OAuth

Now after searching NuGet I saw that there is a C# WooCommerce library out there all ready written called WooCommerce.NET. This isn’t going to work for me because I will need the ability to gain access to custom Order fields.

So I decided to just use my favorite REST client RestSharp to contact a fairly simple REST API for WooCommerce. But I was running into a strange authentication issue and being denied authentication with a 401 status code.

Now, first a disclaimer… DO NOT USE HTTP FOR WooCommerce IN A PRODUCTION ENVIRONMENT!

Ok, but I need to do some testing in a local environmnet so I can see that my code is working properly. Reading the WooCommerce documentation for authentication, which can be found here, it clearly states:

The OAuth parameters must be added as query string parameters and not included in the Authorization header. This is because there is no reliable cross-platform way to get the raw request headers in WordPress.

So I do a bit of digging about RestSharp and OAuth1.0 and come up with this suite of tests. Here’s the important bit that I needed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[Test]
public void Can_Authenticate_OAuth1_With_Querystring_Parameters()
{
const string consumerKey = "enterConsumerKeyHere";
const string consumerSecret = "enterConsumerSecretHere";
const string baseUrl = "http://restsharp.org";
var expected = new List<string>
{
"oauth_consumer_key",
"oauth_nonce",
"oauth_signature_method",
"oauth_timestamp",
"oauth_version",
"oauth_signature"
};

RestClient client = new RestClient(baseUrl);
RestRequest request = new RestRequest(Method.GET);
var authenticator = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret);
authenticator.ParameterHandling = OAuthParameterHandling.UrlOrPostParameters;
authenticator.Authenticate(client, request);

var requestUri = client.BuildUri(request);
var actual = HttpUtility.ParseQueryString(requestUri.Query).AllKeys.ToList();

Assert.IsTrue(actual.SequenceEqual(expected));
}

The above Authenticate method will do all the work and add all the parameters I need.

But wait… Something’s not right here. In the debugger it shows me that the parameters on the request are being added as cookes:

Visual Studio Debugger

Strange, but ok. So I decided to make an extension method that does all the authentication, gets all the parameters added to the request, and then converts them to QueryString parameters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static class RestRequestExtensions
{
public static RestRequest BuildOAuth1QueryString(this RestRequest request, RestClient client, string consumerKey, string consumerSecret)
{
var auth = OAuth1Authenticator.ForRequestToken(consumerKey, consumerSecret);
auth.ParameterHandling = OAuthParameterHandling.UrlOrPostParameters;
auth.Authenticate(client, request);

//convert all these oauth params from cookie to querystring
request.Parameters.ForEach(x =>
{
if (x.Name.StartsWith("oauth_"))
x.Type = ParameterType.QueryString;
});

return request;
}
}

So the code to build a request now looks something like this.

1
2
3
4
var client = new RestClient("http://example.com/api/v1");
var request = new RestRequest("/path/to/resource");
request.BuildOAuth1QueryString(client, "{consumer_key}", "{consumer_secret}");
var response = client.Execute(request);

And there we have it. Talking to WooCommerce with RestSharp.

For Production

I can not stress enough to not communicate over HTTP in production. In production, you should be using HTTPS. In that case you can use HTTP Basic Authentication. Then you will no longer need the BuildOAuth1QueryString extension method, you would simply add the Basic Authentication to the client like so:

1
2
//Basic over Https
client.Authenticator = new HttpBasicAuthenticator("{consumer_key}", "{consumer_secret}");

Hope this helps!


comment: