Securing Requests

Securing requests sent from your JS

We strongly encourage all Castle customers to enable Secure Mode to prevent fraudsters from impersonating your users. This is particularly important when you're using the risk scores from Castle to lock user accounts, where you need to make sure fraudsters can't lock out your users by feeding in bad behavior.

To sign requests, you'll need to generate a signature on your backend, then pass it to the Javascript snippet:

_castle('secure', 'YOUR_GENERATED_SIGNATURE');

The signature is a SHA-256 HMAC in hex format.

The HMAC shared secret is your API Secret, and the value is the User ID being tracked in identify.

Example

<script type="text/javascript">
  _castle('secure',
    '<%= OpenSSL::HMAC.hexdigest("sha256", "YOUR_API_SECRET", "1234") %>');
</script>
<?
<script type="text/javascript">
  _castle('secure',
    '<?= hash_hmac("sha256", "1234", "YOUR_API_SECRET"); ?>');
</script>

Secure mode is activated as soon as we receive your first request using a valid signature. Once enabled, you can disable it in the dashboard.

Securing webhooks received from Castle

Since anyone could in principle send webhooks to your application, it’s important to verify that these webhooks originated from Castle. Valid webhooks will therefore contain the header X-Castle-Signature which points to a HMAC SHA256 signature of the webhook payload (body):

require "json"

# Using Sinatra
require 'rubygems'
require 'base64'
require 'openssl'
require 'sinatra'

helpers do
  # Compare the computed HMAC digest based on the shared secret and the
  # request contents to the reported HMAC in the headers
  def verify_webhook(data, hmac_header)
    digest  = OpenSSL::Digest::Digest.new('sha256')
    calculated_hmac =
      Base64.encode64(OpenSSL::HMAC.digest(
        digest,
        'YOUR_API_SECRET',
        data)
      ).strip
    calculated_hmac == hmac_header
  end
end

# Respond to HTTP POST requests sent to this web service
post '/' do
  request.body.rewind
  data = request.body.read
  hmac_header = request.headers['X-Castle-Signature']
  verified = verify_webhook(data, hmac_header)

  # IMPLEMENT: handle the alert

  # Output 'true' or 'false'
  puts "Webhook verified: #{verified}"
end
<?
function verify_webhook($data, $hmac_header)
{
  $calculated_hmac = base64_encode(hash_hmac('sha256',
                                             $data,
                                             'YOUR_API_SECRET',
                                             true));
  return ($hmac_header == $calculated_hmac);
}

$hmac_header = $_SERVER['HTTP_X_CASTLE_SIGNATURE'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
error_log('Webhook verified: '.var_export($verified, true));
?>