Verifying requests

Learn about securing your incoming webhooks

We recommend verifying the webhook signature to make sure the data received is coming from Trengo.

The Trengo-Signature header is sent with every webhook, it consists of a timestamp and hash concatenated together with a ; in between.
Example signature: 1569508124;1298b36aefaeb7e0e93073744b954266515b69304b3dfe044cbf7203525061f4

The hash is a lowercase hexadecimal SHA256 HMAC digest of the timestamp, a . and the request's body. It uses your signing secret as key.

Compare the hash part of the signature to verify the webhook's authenticity.

<?php

$payload = @file_get_contents('php://input'); // The request's body
$signature = $_SERVER['HTTP_TRENGO_SIGNATURE']; // The Trengo-Signature header value
$signingSecret = 'my-secret'; // Your signing secret

// verify the signature
if (verify($payload, $signature, $signingSecret)) {
  echo 'Valid signature.';
} else {
  echo 'Invalid signature';
}

/**
 * @param $payload
 * @param $signature
 * @param $signingSecret
 * @return bool
 */
function verify($payload, $signature, $signingSecret) {
  list($timestamp, $hash) = explode(';', $signature);

  return hash_equals(hash_hmac('sha256', $timestamp . '.' . $payload, $signingSecret), $hash);
}
var express = require('express');
var CryptoJS = require('crypto-js');

// start the express server
var app = express();
app.listen();

// parse the URLEncoded body and save the raw body to req.rawBody
app.use(
  express.urlencoded({
    verify: function (req, res, buf) {
      req.rawBody = buf;
    },
    inflate: true,
    type: "application/x-www-form-urlencoded"
  })
);

// listen for POST requests to '/my-endpoint'
app.post('/my-endpoint', function(req, res) {
  // replace with your signing secret, found in Trengo
  var signingSecret = 'my-secret';
  // get signature header
  var signature = req.header('Trengo-Signature');
	// get raw request body
  var payload = req.rawBody;

  // verify the signature
  if (verify(payload, signature, signingSecret)) {
    res.send('Valid signature');
    // the parsed body is available at req.body
    console.log(req.body);
  } else {
    res.send('Invalid signature');
  }
});

// the function to verify the trengo-signature
function verify(payload, signature, signingSecret) {
  // split the timestamp from the hash
  var signatureParts = signature.split(';');
  var timestamp = signatureParts[0];
  var hash = signatureParts[1];

  // get the raw digest bytes
  var raw = CryptoJS.HmacSHA256(timestamp + '.' + payload, signingSecret);

  // encode the raw bytes as hexadecimal digits
  var hex = raw.toString(CryptoJS.enc.hex);

  // and make the hexadecimal digits lowercase
  var lowerCase = hex.toLowerCase();
  
  // compare the result to the hash from the signature header
  return lowerCase === hash;
}