Ingesting Facebook webhooks (challenge & verification)

By Karolis Rusenas · Sep 22, 2020

Facebook lets you receive information about various events via webhooks. Documentation can be found here https://developers.facebook.com/docs/messenger-platform/getting-started/webhook-setup/. These webhooks are almost like any other webhooks except they also ask you to do the verification of the token (similarly to shared secret and HMAC in other platforms) but the slight difference comes when dealing with the challenge.

In this short tutorial, I will demonstrate how to configure Facebook webhooks so Webhook Relay will solve the challenge for you.

Facebook webhooks

You can read more about the Messenger Platform here: https://developers.facebook.com/docs/messenger-platform/introduction.

Create a bucket in Webhook Relay

First, create a new Webhook Relay bucket. You can do that by visiting buckets page.

Creating Webhook Relay bucket

Here, you will see your “Default public endpoint” that should look like <random letters>.hooks.webhookrelay.com.

Configure webhooks endpoint on Facebook

Configuring Facebook webhooks

Click on subscribe and then add your Webhook Relay public endpoint:

Adding Webhook Relay endpoint to Facebook

If you click on “Verify and Save” it will show you an error and looking at the request in the Webhook Relay dashboard, we can see that the query had several values Query: hub.mode=subscribe&hub.challenge=1903260781&hub.verify_token=my-facebook-token .

We need to take the challenge and set it as a header.

Solving the Facebook webhook verification challenge

The way to solve the Facebook verification challenge is to get the value from the URL query and set it to the response body. This can be achieved with the Webhook Relay Function.

Go to Functions page https://my.webhookrelay.com/functions and create a new function called “facebook-verification”.

Copy paste the code below:

local mode = r.RequestQuery["hub.mode"]

if mode == "subscribe" then
    r:SetResponseBody(r.RequestQuery["hub.challenge"])
end

Now, go back to the bucket that you have previously created, click on the Inputs and then “CONFIGURE” on your input:

Setting up function

Now, if you try “Save and Verify” again from the Facebook webhooks page, it should pass.

You can now try sending some “test” events from the platform:

Sending test event

Facebook webhook token authentication

Facebook also sends a token that you have supplied when adding configuration. In my example, it was my-facebook-token. We can get this value too and verify in the Function:

local mode = r.RequestQuery["hub.mode"]

-- Shared secret - replace with yours!! 
local my_shared_secret = "my-facebook-token"

-- If mode is subscribe, validating it
if (mode == "subscribe") then
  -- Getting verify token
  local token = r.RequestQuery["hub.verify_token"]
  -- Validating token
  if not(token == my_shared_secret) then  
    r:SetResponseStatusCode(401)
    r:StopForwarding()
    return
  end
  -- Responding to challenge
  r:SetResponseBody(r.RequestQuery["hub.challenge"])
end

Update the function, remove Facebook subscription and then try again.

That’s it, you can now configure destinations either to your public or private application servers and start processing Facebook webhooks.