Runscope API Testing and Monitoring    Learn More →

Using Runscope to Test APIs Protected with the Hawk Authentication Scheme

By Gustavo Straube on .

We’re excited to have Gustavo Straube, Software Engineer and Co-founder at both Creative Duo and All Day Use, show the Runscope community how to test APIs that use alternative or custom authentication schemes.

Nowadays, employing authentication protocols with your APIs is a necessity, but dealing with them can be taxing. At Creative Duo, we usually build APIs to act as the backend for mobile apps and modular systems. In both cases, even when using TLS protocol to protect the data, we have to guarantee that only authorized requests get a valid response from any service. In the past, we used a home-grown solution to avoid unwanted access, but it wasn't reliable and writing a trusty security protocol has never have been our focus.

After trying some alternatives, we ended up choosing Hawk authentication scheme for its simplicity and ease of integration. It provides enough safety for our applications and their consumers. The primary design goals of Hawk are to:

  • Simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources
  • Secure credentials against leakage
  • Avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client failure to validate the server's identity as part of its TLS handshake

As we started to configure the first test we found a little problem in our way: the API we were testing uses Hawk for authentication, and we only found options for Basic Authentication and OAuth 1.0.

Checking the available configurations, there was an option to add static headers. However, as a replay protection procedure, authentication headers in Hawk are valid for only one minute. With that in mind, the static header was not an option since we must update the header within one minute. Furthermore, automatic tests would be impossible to run.

Recently we discovered Runscope and its awesome features to monitor and test APIs. After a tweet exchange a few emails with Runscope team, we got a script to start with. Yes! It is possible to write scripts to run before (initial scripts) and after tests. The scripts should be written in Javascript, which is a great choice since a lot of developers know at least a bit of JS. Also, it's possible to use a few common libraries with scripts, like Moment.js and CryptoJS.

Creating the Authentication Header

Before creating the dynamically generated authentication headers, we must set up some variables we'll use in the script.

Now we can start to build the header itself. Hawk protocol is simple: it basically uses an HMAC hash, created with the request info, using a secret key.

Knowing the protocol basics, the following code becomes pretty obvious.

Step 1: Set up the request data into variables.

var now = parseInt(moment() / 1000);
var method = "GET";
var path = "/api/path/to/resource";
var host = "example.com";
var port = 80;
var ext = null;
var nonce = Math.random().toString(36).substring(6);

Step 2: Create the normalized request string, with each value followed by a newline, as required by the protocol.

var artifacts = "hawk.1.header\n" + now + "\n" +
     nonce + "\n" +
     method + "\n" +
     path + "\n" +
     host + "\n" +
     port + "\n\n";
if (ext) {
     artifacts += ext;
}
artifacts += "\n";

Step 3: Create the hash using the HMAC function from CryptoJS.

var mac = CryptoJS.HmacSHA256(artifacts, variables.get("hawkSecret")).toString(CryptoJS.enc.Base64);

Step 4: Build the authorization header contents.

var header = "Hawk id=\"" + variables.get("hawkKey") + "\", ts=\"" + now +
"\", nonce=\"" + nonce + "\"";
if (ext) {
       header += ", ext=\""+ ext + "\"";
}
header += ", mac=\"" + mac + "\"";

Step 5: Set the header contents to a variable to use in the request configuration.

variables.set("hawkHeader", header);

Now that we have an authorization header, which changes according to the time, we can add it to our request, using the variable from the script.

Finally, we can run our test, check the response and add some assertions.

Initial scripts run before the request, so we cannot retrieve data from the request to use when creating the header. That is why we set all request parameters in the script (method, host, path, etc.). To avoid modifying the script for each different test configuration, we can create variables for all those settings which change between tests so that we can simply copy and paste the script when needed.

At Ease with API Testing & Auth Tools

Now that we've found an auth solution that works well for us, we're put even more at ease having a tool like Runscope in our arsenal to monitor and test the health all of those APIs. If you have any questions or comments about using Hawk protocol or testing APIs using authentication schemes, feel free to leave a comment below or tweet at me!

You can start testing APIs protected by an authentication protocol by signing up for Runscope for free. 

Categories: code samples, howto, product, monitoring, security, testing, community

Everything is going to be 200 OK®