Skip to content Skip to sidebar Skip to footer

Using Javascript To Properly Sign A String Using Hmacsha256

In the Houndify API Docs for Authentication, you have the following block of content: An Example of Authenticating a Request Let's assume we have the following information: UserID

Solution 1:

According to the documentation, if you're using one of their SDKs, it will automatically authenticate your requests:

SDKs already handle authentication for you. You just have to provide the SDK with the Client ID and Client Key that was generated for your client when it was created. If you are not using an SDK, use the code example to the right to generate your own HTTP headers to authenticate your request.

However, if you want to do it manually, I believe you need to compute the HMAC value of the string they describe in the link in your question and then send it base64 encoded as part of the Hound-Client-Authentication header in your requests. They provide an example for node.js:

var uuid = require('node-uuid');
var crypto = require('crypto');

functiongenerateAuthHeaders (clientId, clientKey, userId, requestId) {

    if (!clientId || !clientKey) {
        thrownewError('Must provide a Client ID and a Client Key');
    }

    // Generate a unique UserId and RequestId.
    userId      = userId || uuid.v1();

    // keep track of this requestId, you will need it for the RequestInfo Object
    requestId   = requestId || uuid.v1();

    var requestData = userId + ';' + requestId;

    // keep track of this timestamp, you will need it for the RequestInfo Objectvar timestamp   = Math.floor(Date.now() / 1000),  

        unescapeBase64Url = function (key) {
            return key.replace(/-/g, '+').replace(/_/g, '/');
        },

        escapeBase64Url = function (key) {
            return key.replace(/\+/g, '-').replace(/\//g, '_');
        },

        signKey = function (clientKey, message) {
            var key = newBuffer(unescapeBase64Url(clientKey), 'base64');
            var hash = crypto.createHmac('sha256', key).update(message).digest('base64');
            return escapeBase64Url(hash);

        },

        encodedData = signKey(clientKey, requestData + timestamp),
        headers = {
            'Hound-Request-Authentication': requestData,
            'Hound-Client-Authentication': clientId + ';' + timestamp + ';' + encodedData
        };

    return headers;
};

Solution 2:

So basically, signing [in this specific case] simply means to create a hash of the string using a hash algorithm in addition to a key, as opposed to a keyless hash [like MD5]. For example:

var message = 'my_message';
var key = 'signing_key';
var hashed_message = hash_func(message, key);

where hash_func is a hashing algorithm like HmacSHA256 (the hashing algorithm in question).

The reason I was trying to figure this out was to test authentication for the Houndify API using Postman. Fortunately, Postman has a nice feature called pre-request scripts [complete with hashing algorithms] that helps if you need to pre-generate values that need to be sent along with your request.

After much fiddling around, I managed to create a pre-request script that properly authenticates to this API (see code below).

var unescapeBase64Url = function (key) {
            return key.replace(/-/g, '+').replace(/_/g, '/');
        },

        escapeBase64Url = function (key) {
            return key.replace(/\+/g, '-').replace(/\//g, '_');
        },
        guid = function() {
    functions4() {
        returnMath.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
    returns4() + s4() + '-' + s4() + '-' + s4() + '-' +
        s4() + '-' + s4() + s4() + s4();
    };

var client_id_str = environment["client-id"];
var client_key_str = environment["client-key"];
var user_id_str = environment["user-id"];
var request_id_str = guid();
var timestamp_str = Math.floor(Date.now() / 1000);

var client_key_dec_str = CryptoJS.enc.Base64.parse(unescapeBase64Url(client_key_str));

var message_str = user_id_str+";"+request_id_str+timestamp_str;
var signature_hash_obj = CryptoJS.HmacSHA256(message_str, client_key_dec_str);
var signature_str = signature_hash_obj.toString(CryptoJS.enc.Base64);

var hound_request_str = user_id_str+";"+request_id_str;
var hound_client_str = client_id_str+";"+timestamp_str+";"+escapeBase64Url(signature_str);

postman.setEnvironmentVariable("hound-request-authentication", hound_request_str);
postman.setEnvironmentVariable("hound-client-authentication", hound_client_str);

Note that you are going to have to create environment variables in Postman for client-id, client-key, and user-id, as well as for the header variables hound-request-authentication and hound-client-authentication to hold the final values that will be referenced when defining headers.

Hope it helps.

Post a Comment for "Using Javascript To Properly Sign A String Using Hmacsha256"