15

I am a developer and I am looking for some software to provide our QA for testing REST API that requires SHA1 HMAC authentication (each request is signed using user's secret key, the process is described here).

Usually I use Postman or Rest Console, but I could not set up request signing as required. Are there some tools that could do the job?

upd. I tried to write Postman pre-request script with no luck. I can share my work if someone is interested in continuing it.

  • It is something added into the http-headers, right? Similar to token-based authentication. Have you tried put together the http package by http client? Did it work? – SayusiAndo Apr 15 '15 at 7:26
  • Yes, that's in http headers. The request data is hashed with the timestamp and secret key, so the header should be pre-calculated just after every request start but before it's sent to the server. I did not try http package, not sure what do you mean. – Aldekein Apr 15 '15 at 12:59
  • What language do you use? I'll bring some example. – SayusiAndo Apr 15 '15 at 13:14
  • As I wrote: "I am looking for some software to provide our QA for testing". I have an API client that works great, but I cannot give it to QA and say "Just learn some programming and you'll be fine" :) – Aldekein Apr 15 '15 at 14:07
  • Ohh, sorry, I see your point! Let me go through the process description and we will see whether I can say something smart. – SayusiAndo Apr 15 '15 at 14:11
18

Note that when I wrote this jQuery was built into Postman. Since v4.5.0 it has been replaced by CheerioJS and Lodash, so this solution won't work with v4.5.0+.

I successfully got custom HMAC SHA256 header signing in Postman working using Pre-request script. Here's how I did it:

Per the Postman documentation, you can't set request headers directly. In the pre-request script you have to assign the header value to a global or environment variable, and then use the header variable in the header key-value editor.

Here's an example of using environment variables in Headers:

enter image description here

Here's the pre-request script I wrote to generate the values needed, and assign to the header variables:

var key = 'my_api_key';
var base64Secret = 'my_b64_secret';

function newGuid() {
    return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); });
}

function epochTime() {
    var d = new Date();
    var t = d.getTime();
    var o = t + "";
    return o.substring(0, 10);
}

// Load required 3rd party JS libs via jQuery
// http://stackoverflow.com/a/11803418

$.when(
    $.getScript( "https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.0.1/sha256.js" ),
    $.getScript( "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/md5.js" ),
    $.getScript( "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js" ),
    $.Deferred(function( deferred ){
        $( deferred.resolve );
    })
).done(function(){

    var time = epochTime();
    var nonce = newGuid();
    var method = request.method;
    var encodedUri = encodeURIComponent(request.url).toLowerCase();

    // Build the request body string from the Postman request.data object
    var requestBody = "";
    var firstpass = true;
    for(var param in request.data)
    {
        if(!firstpass){
            requestBody += "&";
        }
        requestBody += param + "=" + request.data[param];
        firstpass = false;
    }

    var b64BodyContent = "";
    if(requestBody){
        // MD5 hash and convert the request body string to base 64
        b64BodyContent = CryptoJS.MD5(requestBody).toString(CryptoJS.enc.Base64);
    }

    var rawSignature = key + method + encodedUri + time + nonce + b64BodyContent;

    // Generate HMAC SHA256 signature
    // Using library: http://caligatio.github.io/jsSHA/
    var shaObj = new jsSHA("SHA-256", "TEXT");
    shaObj.setHMACKey(base64Secret, "B64");
    shaObj.update(rawSignature);
    var signature = shaObj.getHMAC("B64");

    postman.setEnvironmentVariable('key', key);
    postman.setEnvironmentVariable('time', time);
    postman.setEnvironmentVariable('nonce', nonce);
    postman.setEnvironmentVariable('signature', signature);
});
  • 3
    This is absolutely wonderful. In a single answer you've provided a more instructive tutorial on pre-request scripts than the Postman site even does. Well done sir! – Pierce Feb 3 '16 at 20:38
  • Mine complains about the $ jquery character. Did you have to tell postman to use jquery somehow? – Joe Phillips May 2 '18 at 23:15
  • It seems jquery was removed and it uses cheerio now? Not sure how to translate this though... – Joe Phillips May 2 '18 at 23:28
16

I know this is an old thread, but I found it looking to resolve the same problem. The use of JQuery in Postman as suggested in one of the answers is no longer viable, it's been deprecated. But here's what I came to in the end, using Postman's current version (v4.3.9 at the time of writing this).

Postman's pre-request scripts give you access to the request body and allow you to set environmental variables that can then be used to set your request's header values. The script also gives you access to a few popular libraries including CryptoJS.

So, inside the Pre-request Script editor, paste

postman.setGlobalVariable("hmac", CryptoJS.HmacSHA256(request.data, <secret>));

Then, in the Headers editor set a HMAC header with the value of the global hmac variable, e.g: enter image description here

2

I don't have enough reputation to comment, @David got me into the correct neighborhood for the current version. Review the documentation for the Postman Sandbox which includes Global Variables.

I needed a signature header which was a sha1 hash of the request's payload, I accomplished this by adding the header as:

[{"key":"signature","value":"{{signature}}","description":"","enabled":true}]

and calculating the hash using the Pre-request Script:

pm.globals.set("signature", CryptoJS.HmacSHA1(request.data, "secret"));

0

I am not sure if i have understood your problem correctly, but my best guess says you are trying to generate keys for auth. You could try https://quickhash.com/

  • Sorry, that wouldn't work. The hash need to be calculated automatically just before sending the request. Nobody will copy-paste request data manually (and it's impossible because hash includes request timestamp which is known only in time of sending the request). – Aldekein Jan 15 '15 at 2:26
0

Have you looked into SoapUI? This is pretty comprehensive, fairly powerful and also fairly well known by QAs for testing REST services.

  • I've just done a Google search of "+soapUI hmac sha1" and none of 6 results are relevant. – Aldekein Apr 16 '15 at 10:28
  • @Aldekein that's because your use case is very specific and SoapUI is a framework and not a language. SoapUI can make use of groovy scripting to set properties, which is where you would be able to create your sha1 hash. Hope that helps. – chrisc Apr 16 '15 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.