How to create a webhook using Node, Express and Ngrok

Here is a quick example of how to subscribe to a webhook with a dummy server using a Mac

Step 1

Install ngrok using Homebrew, as documented here.

For Homebrew v2.6.x and below:

brew cask install ngrok

For Homebrew v2.7.x and above:

brew install --cask ngrok

Sign up for a free ngrok account.

Install your authtoken. To find YOUR_TOKEN, go to your ngrok dashboard.

In terminal, run:

ngrok authtoken YOUR_TOKEN

If you receive a “No such file or directory” error, try navigating to the /usr/local/bin directory and rerunning the command as follows:

cd /usr/local/bin
ngrok authtoken YOUR_TOKEN

Please refer to ngrok’s documentation for further clarification.

Step 2

Install Node.js. We are using homebrew to install Node.js, but you can also download it here.

Open a terminal and run:

brew install node

Step 3

Create a new Node.js project in terminal:

mkdir strava-webhooks
cd strava-webhooks
touch index.js 
npm init
npm install express body-parser --save

Step 4

This is is the code to run a dummy server that will help you complete a webhook subscription. It will not process webhook events for you. Please copy/paste the below into index.js:

'use strict';

// Imports dependencies and sets up http server
const
  express = require('express'),
  bodyParser = require('body-parser'),
// creates express http server
  app = express().use(bodyParser.json());

// Sets server port and logs message on success
app.listen(process.env.PORT || 80, () => console.log('webhook is listening'));

// Creates the endpoint for our webhook
app.post('/webhook', (req, res) => {
  console.log("webhook event received!", req.query, req.body);
  res.status(200).send('EVENT_RECEIVED');
});

// Adds support for GET requests to our webhook
app.get('/webhook', (req, res) => {
  // Your verify token. Should be a random string.
  const VERIFY_TOKEN = "STRAVA";
  // Parses the query params
  let mode = req.query['hub.mode'];
  let token = req.query['hub.verify_token'];
  let challenge = req.query['hub.challenge'];
  // Checks if a token and mode is in the query string of the request
  if (mode && token) {
    // Verifies that the mode and token sent are valid
    if (mode === 'subscribe' && token === VERIFY_TOKEN) {     
      // Responds with the challenge token from the request
      console.log('WEBHOOK_VERIFIED');
      res.json({"hub.challenge":challenge});  
    } else {
      // Responds with '403 Forbidden' if verify tokens do not match
      res.sendStatus(403);      
    }
  }
});

Step 5

Start the node server by running the following in terminal:

node index.js

Step 6

Open a new tab and start ngrok so your local server is reachable by internet:

ngrok http 80

Step 7

Log in or create a Strava account. After your account has been created, click here to link the Node server you created in Steps 3 - 6 to your Strava account.

After you create a subscription in step 8, webhook events will be pushed to this app when when an athlete revokes access to an application, or when an activity is created, deleted, or one of the following activity fields are updated, as documented here.

An important field in the App creation form is Authorization Callback Domain; here you’ll want to use the forwarding url listed as the output from Step 6 (e.g. http://xyzabc123.ngrok.io) so that Strava knows where to push webhook events.

Step 8

Finally, make a Postman or cURL request to subscribe to a webhook.

Please change the parameters as the following example includes dummy data: - You can find your client secret and client id on your App info page. - Use the same callback_url that you used in Step 7, appended with /webhook (e.g. http://xyzabc123.ngrok.io/webhook). - Use the verify_tokenfrom Step 4.

curl -X POST \
  https://www.strava.com/api/v3/push_subscriptions \
  -F client_id=12345 \
  -F client_secret=1234567abcdefg \
  -F callback_url=https://1234abcd.ngrok.io/webhook \
  -F verify_token=STRAVA

You should see WEBHOOK_VERIFIED printed to the terminal console if the request was successful.

Step 9

To test that your webhook is working, trigger any of the events listed in Step 7 that will result in the generation of a webhook push event.

If your webhook subscription worked, you’ll see EVENT_RECEIVED printed to the terminal console.