Verifying Requests
Request signatures allow your app to verify the authenticity of incoming webhook traffic. These signatures will be provided as an X-Webflow-Signature HTTP header, which Webflow generates by creating a HMAC hash of the request timestamp and body using your OAuth Application's Client Secret
as the hash key.
While request validation is not required for receiving Webflow webhook requests, it is highly recommended.
Signatures are only included in OAuth Apps
Webhooks created via a site's dashboard or with a Site's API Key will not include request signatures. If you would like to utilize request signatures, please regenerate your webhooks using an OAuth application.
Validating Request Signatures
To validate a Webflow webhook request, you'll need to create an HMAC hash using the values of the request's X-Webflow-Timestamp
header, the X-Webflow-Signature
header, and your OAuth Application's Client Secret
.
Request validation is a two steps process:
Validate the Timestamp
Checking the age of the request timestamp included in X-Webflow-Timestamp
. If the request is older than 5 minutes, this may indicate a replay attack.
Validate the Request Body
Create a hash from the combination of the request body, a :
, and the timestamp.
Number(request_timestamp) + ":" + JSON.stringify(request_body)
Then compare the hash with the X-Webflow-Signature
request header.
Node.js Example
Incoming Request Headers
[X-Webflow-Timestamp, 1663849649733]
[X-Webflow-Signature, db37faac5680c551e1860d6cf88c261565c25bdf0c8275d5d71f24ee079bb7ca]
Validation
// Import Node's Crypto module
import crypto from 'crypto';
// Webhook Request Validation
function validateRequestSignature(signature, timestamp, body, consumer_secret){
// Return false if timestamp is more than 5 minutes old
if (((Date.now() - Number(timestamp)) / 60000) > 5){
return false
};
// Concatinate the request timestamp header and request body
const content = Number(request_timestamp) + ":" + JSON.stringify(request_body);
// Generate an HMAC signature from the timestamp and body
const hmac = crypto
.createHmac('sha256', consumer_secret)
.update(content)
.digest('hex');
// Create a Buffers from the generated signature and signature header
const hmac_buffer = Buffer.from(hmac);
const signature_buffer = Buffer.from(request_signature);
// Compare generated signature with signature header checksum and return
return crypto.timingSafeEqual(hmac_buffer, signature_buffer);
}
// Get request body, timestamp and signature headers
request_body = request.body();
request_timestamp = request.headers['X-Webflow-Timestamp'];
request_signature = request.headers['X-Webflow-Signature'];
// Validate the request signature to ensure this request came from Webflow
if (validateRequestSignature(request_signature, request_timestamp, request_body, consumer_secret)) {
// Process the request
} else {
// Reject the request
}
Other Examples
We've provided an example Javascript implementation to the right, but most modern programming languages have modules and tutorials for HMAC validation.
Updated 5 months ago