Securing Webhook Form Integrations
Webhooks enable the automatic transmission of information from your Form Widget entries to an external server or service you control. It's crucial to configure your receiving server to accept webhook requests only from trusted sources.
Overview
Note: Implementing these security practices requires familiarity with server-side code. ShortStack's support team cannot assist with specific configurations on your server(s).
Adding and validating a secret key
Securing your receiving server can be effectively achieved by providing an optional secret key in your webhook settings.
Configure the webhook integration
Open your Form Container's webhook integration settings.
Create a new random string to use as your secret key.
For example, in your terminal, run:
<span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;"></span><code class="language-ruby!whitespace-pre hljs" style="font-size: 15px;">ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'</code>
Copy the generated string and paste it into the Secret Key field in your webhook settings.
Save your webhook integration settings.
Configure your receiving server
ShortStack uses the provided secret key to generate an encoded string, sent to your server in the X-Ss-Signature request header. This signature is created by combining the request body with your secret key.
To validate the data received:
Store the Secret Key:
Add an environment variable on your server to store the secret key:
<code class="language-bash!whitespace-pre hljs">export SECRET_KEY=Your_Secret_Key_Here</code>Important: Do not hardcode this key into your application or include it in your version control system.
Implement Signature Verification:
Develop server-side code to verify the signature.
The signature from ShortStack is prefixed with
sha1=. Your verification process should account for this.
Example in Ruby using Sinatra:
<code class="language-ruby!whitespace-pre hljs">require 'sinatra'
require 'openssl'
post '/webhook' do
request.body.rewind
entry_data = request.body.read
secret_key = ENV['SECRET_KEY']
digest = OpenSSL::Digest.new('sha1')
hexdigest = OpenSSL::HMAC.hexdigest(digest, secret_key, entry_data)
signature = 'sha1=' + hexdigest
unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_SS_SIGNATURE'])
halt 403, "Signatures didn't match!"
end
puts entry_data
end</code>Note: It's more secure to use a utility like secure_compare rather than the == operator for comparing signatures.
Alternative security implementations
In addition to using a secret key, consider the following methods to enhance security:
Randomize the endpoint's URL
Creating a complex, hard-to-guess endpoint URL can reduce the likelihood of unauthorized access.
Example: Use a URL like
<code class="language-auto">http://www.example.com/webhooks/d92g5v0tnbji0d3czkfj</code>instead of
<code class="language-auto">http://www.example.com/webhooks/new</code>
Note: This method, known as security through obscurity, should not be relied upon as the sole security measure. Combine it with other methods like IP filtering or secret keys.
Whitelist requests from ShortStack's campaign server
Configure your server to accept requests only from ShortStack's IP address:
IP Address: 52.70.122.166
Implementation methods vary based on your server environment:
PHP Users: Compare
$_SERVER['REMOTE_ADDR']to the above IP address.Ruby Users: Utilize the
kickstarter/rack-attackgem for IP filtering.Other Environments: Refer to your web server, framework, or middleware documentation for IP filtering instructions.
By implementing these security measures, you can ensure that your webhook integrations are protected against unauthorized access and data breaches.
Related resources
Was this helpful?
Thanks β that helps us decide what to fix next.
Sorry this missed. Tell us what you needed and we'll get you an answer β and fix the page.