Webhook Signature Verification
To verify the the authenticity that your scheduled webhook was triggered by cronhooks you can check the signature.
- - ASP.NET / C#
- - PHP
- - Typescript / Node
ASP.NET / C#
[Route("api/[controller]")]
public class CronhooksFailureWebHook : Controller
{
    // You can find your endpoint's secret in your API Keys settings
    const string secret = "wh_...";
    [HttpPost]
    public void Index()
    {
      var json = new StreamReader(HttpContext.Request.Body).ReadToEnd();
      var computedSignature = ComputeSignature(secret, json);
      var cronhooksSignature = Request.Headers["Cronhooks-Signature"];
      if (SecureCompare(computedSignature, cronhooksSignature))
      {
        // Verified
      }
    }
    private string ComputeSignature(string secret, string payload)
    {
      var secretBytes = Encoding.UTF8.GetBytes(secret);
      var payloadBytes = Encoding.UTF8.GetBytes(payload);
      using (var cryptographer = new HMACSHA256(secretBytes))
      {
        var hash = cryptographer.ComputeHash(payloadBytes);
        return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
      }
    }
    private bool SecureCompare(string a, string b)
    {
      if (a.Length != b.Length)
      {
        return false;
      }
      var result = 0;
      for (var i = 0; i < a.Length; i++)
      {
        result |= a[i] ^ b[i];
      }
      return result == 0;
    }
}
                
            PHP
$webhook_secret = 'wh_...';
$payload = @file_get_contents('php://input');
$cronhooks_sig_header = $_SERVER['HTTP_CRONHOOKS_SIGNATURE'];
$signature = computeSignature($payload, $webhook_secret);
if(secureCompare($cronhooks_sig_header, $signature)){
  // Verified
}
private function computeSignature($payload, $secret){
   return hash_hmac("sha256", $payload, $secret);
}
private function secureCompare($secret, $computed){
  if(function_exists('hash_equals')){
    return hash_equals($secret, $computed);
  }
  if (strlen($secret) != strlen($computed)) {
    return false;
  }
  $result = 0;
  for ($i = 0; $i < strlen($secret); $i++) {
    $result |= ord($secret[$i]) ^ ord($computed[$i]);
  }
  return ($result == 0);
}
            
        Typescript / Node
import crypto from 'crypto'
const cronhooksSignature = req.headers['cronhooks-signature']; // req.headers['Cronhooks-Signature']
let body = rawBody.toString();
const expectedSignature = crypto
  .createHmac('sha256', process.env.CRONHOOKS_SECRET)
  .update(body)
  .digest('hex');
let isValidRequest = (cronhooksSignature !== expectedSignature);