Signature Verification

Verifying the request signature

Each webhook request will include a Slope-Signature header that may be used to verify the request. The header value takes on the format:

POST https://your-website.com/slope-webhook HTTP/1.1
Slope-Signature: <timestamp>;<algorithm>=<hmac>,<algorithm>=<hmac>
  • timestamp is the Unix timestamp at which the request was sent. It is used to generate the signature digests to help prevent replay attacks.
  • algorithm describes the hash function used to compute the HMAC value.
  • hmac is the HMAC value that should be compared against.

The request may include a comma-separate list of algorithm-HMAC pairs (<algorithm>=<hmac>) in the event of multiple webhook secret existing for your endpoint configuration (eg; during webhook secret rotation). When multiple pairs exist, you should verify against each.

Building the expected signature

To build the expected signature, here is an example in Javascript:

// 1. Extract the timestamp and actual signature values from the `Slope-Signature` header. 

var parts = headers['Slope-Signature'].split(';');
var timestamp = parts[0];
var signatures = parts[1].split(',');

// 2. Format the payload to sign:
var payload = timestamp + '.' + JSON.stringify(request.body);
var expected = crypto
      .createHmac('sha256', WEBHOOK_SECRET)
      .update(payload)
      .digest('hex');

// 3. Generate the expected signature and compare:
let isVerified = false;
for (var signature of signatures) {
    if (signature.split('=')[1] === expected) {
        isVerified = true
        break;
    }
}

return isVerified;

🚧

Stale timestamps

To protect against replay attacks, you should also ensure the signature's timestamp is not too old. We recommend no older than 5 minutes but the threshold is up to you.