Using Realtime Webhooks with AWS Lambda

  • Sep 28, 2016
  • Messaging
  • Webhooks
  • Serverless

Realtime Webhooks are HTTP callbacks triggered by a Realtime event, such as a new user connection or a message published. In simple terms a given endpoint will be invoked whenever some predefined event occurs in the Realtime network.

AWS Lambda is a compute service where you can upload your code to AWS Lambda and the service can run the code on your behalf using AWS infrastructure. After you upload your code and create a Lambda function, AWS Lambda takes care of provisioning and managing the servers that you use to run the code.

This guide uses the same simple validation example used in the Realtime Webhooks Starting Guide.

We'll be using the same Node.js function as our AWS Lambda function, with the required changes to adapt it to the AWS Lambda interface.

Creating the AWS Lambda function

To create an AWS Lambda function, login to your AWS Management Console and select the AWS Lambda service from the services list.

  • Click the Create a Lambda function and select Skip from the Select blueprint page
  • Since we don't want to associate our new function to an AWS trigger select Next from the Configure triggers page
  • In the Configure function page enter validate as the function name and select Node.js 4.3 as the Runtime
  • In the Lambda function code pane select Edit code inline as Code entry type
  • Paste the following code, replacing the code snippet automatically generated by AWS

'use strict';
var crypto = require("crypto");

exports.handler = (event, context, callback) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    
    // Your Realtime private key
    var privateKey = "ENTER-HERE-YOUR-REALTIME-PRIVATE-KEY";
    
    // Compute the event.body signature for security
    var signature = crypto.createHmac("SHA256", privateKey).update(event.body).digest('hex');
    
    // Get the triggers array
    var triggers = JSON.parse(event.body).triggers;
     
    // iterate through all the triggers
    for(var t = 0; t < triggers.length; t++) {
        var isValid = false;

        // compare the signatures
        if(signature == event.headers['x-realtime-signature']) {
            // signature is valid
            // check if the trigger message has all the required fields
            try {
                var message = JSON.parse(triggers[t].message);
                if((message.sender && message.timestamp > 0 && message.text)) {
                    isValid = true;
                }
            }
            catch(e) {
                // message is not valid
            }
            finally {
                if(isValid) {
                    // the message is valid
                    triggers[t].statusCode = 200;
                } else {
                    // the message is invalid
                    // return an exception
                    triggers[t].statusCode = 400;
                    triggers[t].message = "Message is not valid"
                }
            }
        } else {
            // the message signature is not valid
            // return an exception
            triggers[t].statusCode = 403;
            triggers[t].message = "Message signature is not valid"
        }
    }

    // Prepare the response
    var response = {
        statusCode: 200,
        body: JSON.stringify(triggers)
    };
    
    console.log("response: " + JSON.stringify(response))
    
    // Send the response
    context.succeed(response);
};

In the Lambda function handler and role keep the index.handler as Handler and for the Role choose an existing role or create a new role from template(s).

  • If you have selected the Create new role from template(s) enter a role name (e.g. lambda-access) and select Simple Microservices permissions from the Policy templates list.
  • Keep the Advanced settings as they are and click Next
  • Review your settings and if they are correct click the Create function button.

Your Lambda function is created and you're almost ready to use it in a Realtime webhook.

Configuring the AWS API Gateway

To make your Lambda publicly accessible through a HTTP POST you need to configure the AWS API Gateway using your function as the backend for the API.

In your AWS Management Console select the API Gateway from the AWS services and click the Getting started or Create API buttons (depending whether you have already an API configured or not)

  • In the Create new API page select New API and enter webhooks as the API name.
  • Click the Create API button
  • Select the Actions drop-down list and select the Create Resource option
  • Check the Configure as proxy resource option and enter validate as the Resource Name and {proxy+} in the Resource Path
  • Leave the Enable API Gateway CORS option unchecked and click the Create Resource button
  • Keep the Lambda Function Proxy selected as Integration type and select the region where you have created your Lambda function in the Lambda region drop-down list (probably it's the same region where you are creating the API Gateway).
  • Enter validate as the Lambda Function and click the Save button
  • In the Add Permission to Lambda Function pop-up window select OK

If all went well you'll see something like this:

This means your API will respond to ANY HTTP method and that the API Gateway will automatically forward the request payload to your Lambda function. The same will happen with the response.

Deploying your API

The next step is deploying your API so it becomes ready to use.

  • In the Actions drop-down select Deploy API
  • Select [New Stage] in the Deployment stage and enter prod (or anything you like to identify this stage) in the Stage name
  • Click the Deploy button

Your API is now ready to use and you can find the invoke URL on the blue box as shown below:

Take note of this URL as you'll need to enter it as your Realtime webhook URL.

Configuring the Realtime Webhook

Login to the Realtime Account Management website and open your subscription list. Expand the Realtime subscription where you wish to configure the webhook and select the "Webhooks" option.

Select the "Add new webhook" button and enter the appropriate data into the form fields as explained below:

  • Event
    Select A message was published
  • Channel
    Enter the channel name to bind the webhook. Let's use chat:*
  • URL
    Select Use an external URL and enter your AWS API Gateway invoke URL from the previous section. Don't forget to append /validate
  • Execute
    Keep the Before message is delivered to subscribers option selected

And that's it! Click the SAVE button to start using your AWS Lambda function to validate the messages sent to all sub-channels of the chat channel.

You can learn more about creating API's with AWS Lambda and AWS API Gateway at http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

Get your free Realtime account now

Signup here

If you find this interesting please share: