Knowledge Base/Webhooks/Webhooks Basics

Authenticating webhook requests

Dustin
posted this on May 03, 2013 03:18 PM

Mandrill signs webhook requests so you can (optionally) verify that requests are generated by Mandrill and not a third-party pretending to be Mandrill. If your application exposes sensitive data, you may want to be sure the requests are coming from Mandrill. This isn't required, but offers an additional layer of verification.

Verifying Request Signatures

Mandrill includes an additional HTTP header with webhook POST requests, X-Mandrill-Signature, which will contain the signature for the request. To verify a webhook request, generate a signature using the same key that Mandrill uses and compare that to the value of the X-Mandrill-Signature header.

Get your webhook authentication key

When you create a webhook, a key is automatically generated. If you're using the webhooks/add method, the key will be returned in the response. You can also view and reset the key from the Webhooks page in your account, in the Key column. To retrieve a webhook key via the Mandrill API, use webhooks/info or webhooks/list.

Generate a signature

In your code that receives or processes webhook requests:

  1. Create a string with the webhook's URL, exactly as you entered it in Mandrill (including any query strings, if applicable). Mandrill always signs webhook requests with the exact URL you provided when you configured the webhook. A difference as small as including or removing a trailing slash will prevent the signature from validating.
  2. Sort the request's POST variables alphabetically by key.
  3. Append each POST variable's key and value to the URL string, with no delimiter.
  4. Hash the resulting string with HMAC-SHA1, using your webhook's authentication key to generate a binary signature.
  5. Base64 encode the binary signature
  6. Compare the binary signature that you generated to the signature provided in the X-Mandrill-Signature HTTP header.

Note: Some HMAC implementations can generate either a binary or hexadecimal signature. Mandrill generates a binary signature and then Base64-encodes it; using a hexadecimal signature will not work.

Example PHP implementation

/**
 * Generates a base64-encoded signature for a Mandrill webhook request.
 * @param string $webhook_key the webhook's authentication key
 * @param string $url the webhook url
 * @param array $params the request's POST parameters
 */
function generateSignature($webhook_key, $url, $params) {
    $signed_data = $url;
    ksort($params);
    foreach ($params as $key => $value) {
        $signed_data .= $key;
        $signed_data .= $value;
    }

    return base64_encode(hash_hmac('sha1', $signed_data, $webhook_key, true));
}

Considerations

You can reset a webhook's authentication key at any time. Mandrill will immediately begin using the new key to sign requests. To ensure that you don't lose any webhook batches between the time you reset your key and when you update your application to start using that new key, your webhook processor should reject batches with failed signatures with a non-200 status code. Mandrill will queue the batch and retry later, which will give you time to update your application with the new key.

 
Topic is closed for comments