Skip to content
This repository was archived by the owner on Dec 4, 2024. It is now read-only.

Added request signing #1

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions app/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,32 @@ const server = Fastify({

// Response to Webhooks
server.post("/webhook", async (req, reply) => {
// Get site ID from webhook payload
const { site } = req.body;
// Get signature and timestamp headers for validation
const request_signature = req.headers["x-webflow-signature"];
const request_timestamp = req.headers["x-webflow-timestamp"];

// Get the site's access token
const token = await app.data.get(site);
// Validate the request signature to ensure this request came from Webflow
if (app.validateRequestSignature(request_signature, request_timestamp, req.body, CLIENT_SECRET)){
// Get site ID from webhook payload
const { site } = req.body;

// Initialize a new Webflow client
const webflow = new Webflow({ token });
// Get the site's access token
const token = await app.data.get(site);

// Make calls to the Webflow API
const user = await webflow.get("/user");
// Do other stuff with the API...
// Initialize a new Webflow client
const webflow = new Webflow({ token });

// Return a 200 response to Webflow
reply.statusCode = 200;
// Make calls to the Webflow API
const user = await webflow.get("/user");

// Do other stuff with the API...

// Return a 200 response to Webflow
reply.statusCode = 200;
} else {
// Return a 403 response to Webflow if the request doesn't pass validation
reply.statusCode = 403;
}
});

// Install the App
Expand Down
27 changes: 26 additions & 1 deletion app/webflow.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AuthorizationCode } from "simple-oauth2";
import Client from "webflow-api";
import crypto from "crypto";
import { AuthorizationCode } from "simple-oauth2";
import { Level } from "level";

class App {
Expand All @@ -26,6 +27,30 @@ class App {
authorizeHost: "https://webflow.com",
},
});

// Webhook Request Validation
this.validateRequestSignature = function(signature, timestamp, body_json, 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(timestamp) + ":" + JSON.stringify(body_json);

// 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(signature);

// Compare generated signature with signature header checksum
return crypto.timingSafeEqual(hmac_buffer, signature_buffer);
}
}

/**
Expand Down