Working with Webhooks

A presentation at PHP Barcelona in November 2019 in Barcelona, Spain by Lorna Jane Mitchell

Slide 1

Slide 1

Working with Webhooks Lorna Mitchell, Nexmo

Slide 2

Slide 2

What is a Webhook? An HTTP POST request. @lornajane

Slide 3

Slide 3

Why Webhooks? Event-driven HTTP = Webhooks @lornajane

Slide 4

Slide 4

Webhooks in the Wild @lornajane

Slide 5

Slide 5

Slack Integrations @lornajane

Slide 6

Slide 6

GitHub Builds @lornajane

Slide 7

Slide 7

Webhook Use Cases • Notify of events • Deliver data when available • Broadcast to multiple receivers as-it-happens @lornajane

Slide 8

Slide 8

How APIs Work @lornajane

Slide 9

Slide 9

How APIs Work @lornajane

Slide 10

Slide 10

How APIs Work @lornajane

Slide 11

Slide 11

How Webhooks Work @lornajane

Slide 12

Slide 12

How Webhooks Work @lornajane

Slide 13

Slide 13

What About Time? @lornajane

Slide 14

Slide 14

APIs Over Time @lornajane

Slide 15

Slide 15

Webhooks Over Time @lornajane

Slide 16

Slide 16

Slide 17

Slide 17

Where To Webhook To? @lornajane

Slide 18

Slide 18

Webhooks Need Pre-arrangement With APIs, the client calls the server. With Webhooks, the client has to register with the server, to get data later. … may also agree security (e.g. shared secret) at this stage. @lornajane

Slide 19

Slide 19

Receiving Webhooks Warning: minor tangent ahead @lornajane

Slide 20

Slide 20

Ngrok for Testing Webhooks https://ngrok.com/ - secure tunnel to your dev platform Use this tool to: • webhook into code running locally • inspect the request and response of the webhook • replay requests and see the responses @lornajane

Slide 21

Slide 21

Ngrok for Testing Webhooks Start the tunnel on your laptop: receive a public URL @lornajane

Slide 22

Slide 22

Example: Nexmo SMS When you register a phone number and receive an SMS, your application receives a webhook. @lornajane

Slide 23

Slide 23

I’m running open endpoints on the internet and accepting data, now what? @lornajane

Slide 24

Slide 24

Webhook Security When working with webhooks: • be aware of attack vectors • always use SSL • consider shared secrets and hashing • all good HTTP security practices apply @lornajane

Slide 25

Slide 25

Shared Secrets Share a secret in advance, then transmit all the fields and a signature hash created using the secret. @lornajane

Slide 26

Slide 26

Nexmo SMS Security Nexmo can sign messages using a shared secret. The PHP library https://github.com/nexmo/nexmo-php can do this for you. $signature = new \Nexmo\Client\Signature($_GET, SIGNATURE_SECRET, ‘sha256’); $isValid = $signature->check($_GET[‘sig’]); @lornajane

Slide 27

Slide 27

Slide 28

Slide 28

Receiving Webhooks: Best Practice It’s just an HTTP request! Advice: • DO: accept, store and acknowledge quickly • DON’T: process before acknowledging @lornajane

Slide 29

Slide 29

Using Queues in PHP Applications Queues protect you against bursty traffic. Queues separate work from webservers. • This example uses https://beanstalkd.github.io/ and SlimPHP • Other good alternatives: Redis or Laravel Horizon, Amazon SQS, RabbitMQ @lornajane

Slide 30

Slide 30

SlimPHP and Beanstalkd 1 $container = $app->getContainer(); 2 3 $container[‘queue’] = function ($container) { 4 return new \Pheanstalk\Pheanstalk( 5 getenv(‘QUEUE_HOST’), 6 getenv(‘QUEUE_PORT’) 7 ); 8 }; Pro-tip: Try vlucas\phpdotenv for dev platform environment vars. @lornajane

Slide 31

Slide 31

SlimPHP and Beanstalkd 13 $app->get(‘/webhooks/inbound-sms’, function ($request, $response, $arg 14 $params = $request->getQueryParams(); 15 16 $data = [“event” => “message”, 17 “text” => $params[‘text’], 18 “receivedAt” => date(“U”), 19 “payload” => $params]; 20 error_log(“New message: ” . $params[‘text’]); 21 $this->queue->useTube(‘sms’) 22 ->put(json_encode($data)); 23 }); @lornajane

Slide 32

Slide 32

So The Data is In a Queue. Now What? @lornajane

Slide 33

Slide 33

Let’s talk about Workers Workers are long-running scripts that process a series of jobs. Workers need to be independent: • if things go wrong, exit • separate tool to monitor/restart as needed • beware long-running process hazards • everything processed “at least once” (but maybe more than once, and in any order…) @lornajane

Slide 34

Slide 34

Processing SMS with PHP 14 $queue->watch(“sms”); 15 16 while($job = $queue->reserve()) { 17 $received = json_decode($job->getData(), true); 18 error_log($received[‘text’]); 19 20 // delegate to the class that will do the work 21 $worker->process($received); 22 23 $queue->delete($job); 24 } @lornajane

Slide 35

Slide 35

Processing SMS with PHP 1 class SecureWorker extends Worker { 2 public function process($data) { 3 if ($this->validateMessageSignature($data)) { 4 $this->write_to_file($this->outfile, $data[‘text’]); 5 return true; } 6 } 7 protected function validateMessageSignature($data) { 8 $signature = new \Nexmo\Client\Signature( 9 $data[‘payload’], getenv(‘NEXMO_API_SIGNATURE_SECRET’), ‘s 10 return $signature->check($data[‘payload’][‘sig’]); 11 } @lornajane

Slide 36

Slide 36

Slide 37

Slide 37

Webhooks … are awesome :) @lornajane

Slide 38

Slide 38

Webhooks in Your Applications • Use them WHEN you want to notify other systems • Examples of HOW to use webhooks hopefully gave you some ideas • Webhooks are HTTP: we already understand this @lornajane

Slide 39

Slide 39

Thanks! • PHP Web Services from O’Reilly • Me: https://lornajane.net • Nexmo: https://nexmo.com • Ngrok: https://ngrok.com/ • Code: https://github.com/lornajane/incoming-sms-beanstalkd-php @lornajane