Created
October 28, 2024 14:14
-
-
Save emerleite/beebcd91c8a42c20371979d656c9ed12 to your computer and use it in GitHub Desktop.
Hono middleware - Meta WhatsApp Business API Message Validate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createMiddleware } from 'hono/factory' | |
export function metaValidateWebhookSignature() { | |
return createMiddleware(async (c, next) => { | |
const requestBody = await c.req.arrayBuffer() | |
const payloadSignature = c.req.header('X-Hub-Signature-256') | |
const validRequest = await verifySignature(c.env.META_API_SECRET, requestBody, payloadSignature) | |
console.log('Meta Valid Request?', validRequest) | |
if (!validRequest) { return c.json({ error: 'Invalid signature' }, 403) } | |
await next() | |
}) | |
} | |
/* | |
Meta Docs | |
https://developers.facebook.com/docs/messenger-platform/webhooks/ | |
https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components | |
https://developers.facebook.com/docs/graph-api/webhooks/getting-started#create-endpoint | |
https://developers.facebook.com/docs/whatsapp/cloud-api/guides/set-up-webhooks | |
https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples/ | |
Research | |
https://developers.facebook.com/docs/whatsapp/sample-app-endpoints | |
https://stackoverflow.com/questions/72813196/how-to-register-whatsapp-webhooks-in-nodejs | |
https://glitch.com/edit/#!/whatsapp-cloud-api-echo-bot | |
https://www.linkedin.com/pulse/facebook-webhook-payload-signature-verification-aspnet-rehman-tw8xf/ | |
*/ | |
async function verifySignature(secret, payload, signatureHeader) { | |
if (!signatureHeader || signatureHeader.length == 0) { | |
return false; | |
} | |
const signature = signatureHeader.split('sha256=')[1] | |
if (!signature || signature.length == 0) { | |
return false; | |
} | |
// Encode the secret and the order | |
const encoder = new TextEncoder(); | |
const encodedSecret = encoder.encode(secret); | |
const encodedPayload = new Uint8Array(payload).buffer; | |
// Import the secret key | |
const key = await crypto.subtle.importKey( | |
'raw', | |
encodedSecret, | |
{ name: 'HMAC', hash: 'SHA-256' }, | |
false, | |
['sign'] | |
); | |
// Create the HMAC signature | |
const signatureArrayBuffer = await crypto.subtle.sign( | |
'HMAC', | |
key, | |
encodedPayload | |
); | |
// Convert the ArrayBuffer to a hexadecimal string | |
const calculatedSignature = Array.from(new Uint8Array(signatureArrayBuffer)) | |
.map(byte => byte.toString(16).padStart(2, '0')) | |
.join(''); | |
return signature === calculatedSignature; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment