To make sure the data sent to your webhook endpoint comes from Lemon Squeezy, you need to verify the signature that comes with the event data.
This signature is found in the X-Signature
header. It’s a calculated hash made from a secret key that you set up when creating the webhook through your Lemon Squeezy account, plus the request body.
To confirm that the webhook really comes from Lemon Squeezy, generate a matching hash and compare it with the signature in the header.
This can be done in Cloudflare Workers using the buffer
and crypto
modules.
To use Node.js APIs in your Worker, add the nodejs_compat
compatibility flag to your wrangler.toml
file:
compatibility_flags = [ "nodejs_compat" ]
After that, you can use the following code to verify the signature:
import { Buffer } from "node:buffer";
import { createHmac } from "node:crypto";
export default {
async fetch(request, env, ctx) {
// Get the signature from the request headers
const signature = request.headers.get("x-signature") ?? ""
// Get the raw request body
const body = await request.text();
// Your secret key
const secret = "your-secret";
// Create a hash from the request body using the secret key
const hmac = createHmac("sha256", secret);
const digest = Buffer.from(hmac.update(body).digest("hex"), "utf8");
// Compare the calculated hash with the signature
const signature = Buffer.from(signature, "utf8");
const isValid = crypto.subtle.timingSafeEqual(digest, signature);
if (isValid) {
return new Response("OK", { status: 200 });
} else {
return new Response("Unauthorized", { status: 401 });
}
},
};
This code snippet will verify the signature of the webhook request and return a 200 OK
response if the signature is valid, or a 401 Unauthorized
response if it’s not.