Security

Once your server is configured to receive webhook events, it'll listen for any payload sent to the endpoint you configured. For security reasons, you probably want to limit requests to those coming from Amio. There are few ways to go about this, for example, you could opt to whitelist requests from Amio's IP address but a far easier method is to set up a secret token and validate the information using secret token.

You can find your secret token in Amio settings.

Amio uses this secret token to create a hash signature with each payload. The HTTP request will contain an X-Hub-Signature header which contains the SHA1 signature of the request payload, using the secret token as the key and prefixed with sha1= string. Your callback endpoint can verify this signature to validate the integrity and origin of the payload.

Here is the code how to calculate X-Hub-Signature:

const crypto = require('crypto')

function calculateXHubSignature(secret, body /* as string */) {
  const hmac = crypto.createHmac('sha1', secret)
  hmac.update(body)
  return `sha1=${hmac.digest('hex')}`
}
import org.apache.commons.codec.binary.Hex

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.nio.charset.Charset

class WebhookSecurityService {
  
  public static String calculateXHubSignature(String secret, String body) {
    Mac hmac = Mac.getInstance("HmacSHA1");
    hmac.init(new SecretKeySpec(secret.getBytes(Charset.forName("UTF-8")), "HmacSHA1"));
    return "sha1=" + Hex.encodeHexString(hmac.doFinal(body.getBytes(Charset.forName("UTF-8"))));
  }
}
// credits goes to Michal Pustějovský <[email protected]>

using System;
using System.Text;
using System.Security.Cryptography;

namespace Webhook
{
    public class WebhookSecurityService
    {
        public string WebhookSecurity(string secret, string body)
        {
            var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secret));
            var byteHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
            return "sha1=" + BitConverter.ToString(byteHash).Replace("-", "").ToLower();
        }
    }
}

Verify your algorithm with following values:

secret = 'WebhookSecret'
body = '{"event":"messages_delivered","timestamp":"2018-03-01T11:54:14.886Z","data":{"channel":{"id":"viber_service_messages_test","type":"viber"},"contact":{"phone_number":"+420606123456"},"messages":[{"id":"151990525359991"}]}}'

The calculated X-Hub-Signature should equal to sha1=cb041d03489e961730cb6c7a6d1edf58ae88ef13.