Logo Help Center

Securing Webhooks in Elvis 5

Securing Webhooks in Elvis 5

When making use of Webhooks in Elvis 5, you will probably want to make sure that the received messages are those from Elvis only.

The easiest method to do this is to use the payload signature that is provided by Elvis.

In this process, Elvis will generate a signature for each request by using the payload and the secret token of the Webhook. This is computed as an HMAC Hexdigest and appended to the request headers as an X-Hook-Signature.

To verify the authenticity of the payload, you can compute a hash using the Webhook’s secret token that was generated by Elvis and compare it to the signature in the request.

The following is an example of how this can be achieved using NodeJS and Express.

Imagine you have configured your Webhook to be using the following endpoint:

app.post('/', (request, response, next) => {
    var data = [];
 
    request.on('data', (chunk) => {
        data += chunk;
    });
 
    request.on('end', () => {
        console.log('Data received: ' + JSON.parse(data));
        response.send(null, 200);
    });
 
    request.on('error', (error) => {
        return next(err);
    });
});

 

To add the signature validation, you can do something like:

var crypto = require('crypto');
var compare = require('secure-compare');
 
app.post('/', (request, response, next) => {
    var data = [];
 
    request.on('data', (chunk) => {
        data += chunk;
    });
 
    request.on('end', () => {
            var signature = request.header("x-hook-signature");
 
        if(validateSignature(signature, data)) {
            console.log('Data received: ' + JSON.parse(data));
               response.send(null, 200);
        } else {
            console.log("Signature invalid!");
            response.send("Invalid Elvis WebHook signature.", 400);
        }
 
    });
 
    request.on('error', (error) => {
        return next(err);
    });
});
 
 
function validateSignature(signature, data) {
    var hmac = crypto.createHmac("sha256", secretToken);
    hmac.update(data);
    var digest = hmac.digest("hex");
 
       return compare(digest, signature);
}

Notes

  • For security reasons, do not hard-code the secret token into your application.
  • The use of the === operator to compare the digest to the signature is not recommended. Instead, a package such as secure-compare provides a way to perform a "constant time" string comparison, which renders it safe from certain timing attacks against regular equality operators.
Was this article helpful?
0 out of 0 found this helpful / Created: / Updated:
Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.