// docs

Welcome to Cronhooks docs!

Cronhooks is a powerful webhook scheduling tool designed for developers to automate and manage ad hoc and recurring webhook executions with ease. This documentation provides everything you need to integrate, authenticate, and utilize Cronhooks effectively.

Webhook Signature Verification

To verify the the authenticity that your scheduled webhook was triggered by cronhooks you can check the signature.

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);