Deploy Zoom Video SDK Signature Generator to Amazon Web Services (AWS) Lambda using Claudia.js
Tags: zoom, aws, api, serverless
Published: 2022-11-23 14:29:02

This has been stuck in my mind for the longest time since working on Zoom Developer Platform — using serverless services to expose an endpoint for Zoom Video SDK Signature Generation. For those who are not familiar with Zoom Video SDK or signature generation for SDK Authorisation, you can refer to [Zoom Video SDK documentation](https://marketplace.zoom.us/docs/sdk/video/introduction/) to find out more.

The current [Zoom Video SDK sample signature app](https://github.com/zoom/videosdk-sample-signature-node.js) on the official Zoom Github repository demonstrated the use of Heroku for automatic deployment to your Heroku account to test the app.

Most of the developers I engaged are using either Amazon Web Services (AWS) or Microsoft Azure as the main cloud platform for their application development and deployment. Even those the above mentioned platforms have similar services (managed services) to what Heroku does, there are definitely some merits on the use of [serverless vs. managed services](https://dev.to/perigk/how-different-are-managed-and-serverless-services-1moh).

---

## Approach
The idea here is to provide an easy way to re-use the available sample Express app with minimal changes, deploy to AWS using a Lambda proxy integration approach with API Gateway using Claudia.js. You can find out more on the benefits of using an [API Gateway](https://www.akana.com/blog/api-proxy-vs-api-gateway#why) and [Lambda-Proxy vs Lambda Integration in AWS API Gateway](https://medium.com/@lakshmanLD/lambda-proxy-vs-lambda-integration-in-aws-api-gateway-3a9397af0e6d).

## Our Hero — Claudia.js
The hero for the approach is Claudia.js. **Who is Claudia?**
<figure>
  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dor0gvccm2yut3bksq8q.png">
<figcaption>Image referenced from <a href="https://claudiajs.com/tutorials/installing.html">https://claudiajs.com/tutorials/installing.html</figcaption>
</figure>
<br/>
{% youtube lsXHWy4b-I0 %}
<figcaption>
Claudia.js Introduction
</figcaption>
<br/>
As quoted from [Claudia’s landing page](https://claudiajs.com/):

> Claudia makes it easy to deploy Node.js projects to AWS Lambda and API Gateway. It automates all the error-prone deployment and configuration tasks, and sets everything up the way JavaScript developers expect out of the box.

You can read up more on their page and documentation. In short, Claudia.js does the heavy lifting and the complexity of configuration to deploy Node.js project to AWS Lambda and API Gateway.

This is a good (old) video from AWS that covers in depth on moving Express Apps to Serverless.

{% youtube Cuh_gtFX5gI %}
<figcaption>
<a hrel="https://www.youtube.com/@AWSOnlineTechTalks">AWS Online Tech Talks</a>: Migrate your Existing Express Applications to AWS Lambda
</figcaption>
<br/>

## Prerequisites
Below are the prerequisites that you would already have installed before starting this exercise:
* Visual Studio Code or your favorite IDE
* AWS account with IAM and Lambda access (Free tier will suffice for this exercise)
* [AWS Toolkit Extension for VSC](https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.aws-toolkit-vscode)
* [AWS CLI Tool](https://aws.amazon.com/cli/)
* [Claudia.js](https://claudiajs.com/)

You can refer to the section [**Getting started with Claudia.js**](https://blog.logrocket.com/deploying-a-serverless-api-to-aws-with-claudia-js/) from this link to install Claudia.js and other configurations you may need before we go straight into the current Video SDK sample signature app.

## Exercise

### Modification to Video SDK Sample Signature App
Clone the [sample app](https://github.com/zoom/videosdk-sample-signature-node.js) and open with your IDE. You should see the following project structure. Follow the setup steps in the `README.md`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8zeexhy40cei26gxuus.png)

Open `index.js` and replace line 41 that starts the server locally with an export statement:
```javascript
module.exports = app;
```
Create a new file `local.js` that will imports the app and runs it using the line that was replaced:
```javascript
const app = require('./index');
const port = process.env.PORT || 4000;

// run the server locally
app.listen(port, () => 
  console.log(`Server is listening on port ${port}.`)
);
```
This allows you to run the app locally with `node local.js`.

### Configure Claudia.js
In a nut shell, Claudia uses [aws-serverless-express](https://github.com/awslabs/aws-serverless-express) to generate a helper function to interface and map incoming requests from Amazon API Gateway to the Express routes in the Lambda function. This also reduces the need to manually set up rotes in API Gateway or functions in Lambda.

Open a new Terminal and run the following command in the project directory:
```javascript
claudia generate-serverless-express-proxy --express-module index
```
If your Express.js application module is named differently, replace `index` with the correct name.

`--express-module <<Express.js app name>>` will indicate to Claudia that the Express server is exported from `<<Express.js app name>>.js`.

You can also add a script for the following configuration in `package.json` within the script section:
```javascript
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "start": "node index.js",
  "init-claudia": "claudia generate-serverless-express-proxy --express-module index"
}
```
You can then run the following command:
```
npm run init-claudia
```
---
For both approaches, a new file `lambda.js` will be created and contains the following lambda function:
```javascript
'use strict'
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./index')
const binaryMimeTypes = [
 'application/octet-stream',
 'font/eot',
 'font/opentype',
 'font/otf',
 'image/jpeg',
 'image/png',
 'image/svg+xml'
]
const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes);
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context)
```
The above code add `aws-serverless-express` to the project dependencies.

### Deployment to AWS Lambda
The assumption is that AWS Credentials are properly configured in your IDE. From Claudia.js 2.2.0 onwards, it enables functions to be created without any IAM access and create the related security roles.

In the terminal and run the following command in the project directory:
```
claudia create --handler lambda.handler --deploy-proxy-api --region ap-southeast-1
```
Below are the key parameters from the following command:
* `--handler lambda.handler`: Main function for Lambda to execute, as module.function. In short, we are telling Claudia to deploy the handler function in lambda.js.
* `--deploy-proxy-api`: A proxy API will be created for the Lambda function on API Gateway, and forward all requests to the function.
* `--region <<aws-region>>`: AWS region where to create the function.

For all the available parameters, you can refer to the [documentation](https://github.com/claudiajs/claudia/blob/master/docs/create.md).

Alternatively, you can also add the following configuration in package.json within the script section:
```javascript
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "start": "node index.js",
  "init-claudia": "claudia generate-serverless-express-proxy --express-module index",
  "create-api": "claudia create --handler lambda.handler --deploy-proxy-api --region ap-southeast-1"
}
```
Once deployment is completed, it will save configuration to `claudia.json`:
```javascript
{
  "lambda": {
    "role": "sample-signature-node_js-executor",
    "name": "sample-signature-node_js",
    "region": "[AWS REGION]"
  },
  "api": {
    "id": "[GENERATED API ID]",
    "url": "https://[API ID].execute-api.[AWS REGION].amazonaws.com/latest"
  }
}
```
At this stage, the function is live and you can access the via the url `https://[API ID].execute-api.[AWS REGION].amazonaws.com/latest`.

Based on the sample app, you can make a POST request to the generated url with the following request body using either curl or postman:
```json
{
  "sessionName": "Cool Cars",
  "role": 1,
  "sessionKey": "session123",
  "userIdentity": "user123"
}
```
You should be expecting the response body containing the JSON generated signature. However, you would be getting the following response:
```
terminal ~ % curl -d '{ 
  "sessionName": "Cool Cars",
  "role": 1,
  "sessionKey": "session123",
  "userIdentity": "user123"
}' -H 'Content-Type:application/json' https://[API ID].execute-api.ap-southeast-1.amazonaws.com/latest
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>mac key shall be specified for HS* alg</pre>
</body>
</html>
```
**The question here — Why are we getting this error when all the steps have been followed?**

The answer is simple — **Missing Zoom Video SDK Credentials**. If you recall the setup steps from the sample app `README.md`, an `.env` file is created to store your Video SDK Apps’s Key and Secret and use in local environment.

### Handling environment variables using Claudia
Claudia provides the support for [Lambda Environment Variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) and can provide the variables in a couple of ways.

In the terminal and run the following command in the project directory:

```
claudia update --set-env ZOOM_VIDEO_SDK_KEY=[SDK_KEY],ZOOM_VIDEO_SDK_SECRET=[SDK_SECRET]
```
Go to your AWS Account > Lambda > Functions > [Sample Function], you should be able to see the environment variables added in “Environment variables” under Configuration as shown below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m711txa5nwm015xf8dpi.png)

Make a POST request again and you should be getting a successful response output as shown below.
```
terminal ~ % curl -d '{ 
  "sessionName": "Cool Cars",
  "role": 1,
  "sessionKey": "session123",
  "userIdentity": "user123"
}' -H 'Content-Type:application/json' https://[API ID].execute-api.ap-southeast-1.amazonaws.com/latest
{"signature":"eyJhbGciOiJIUzI[REDACTED]"}
```
You can refer to this link on [Managing Lambda functions](https://claudiajs.com/tutorials/versions.html) on handling different environments and environment variables. Especially for secret management, look at the best practices and what your organization is doing as well.

For the rest of the components, you now can easily configure the settings for API Gateway.

###Final words

Well, this exercise is something that has been top of my mind to find ways to provide an approach for customers using AWS and minimal rework on providing this straightforward services using Serverless functions.

Now back to regular work and more cat photos.

![](https://media.giphy.com/media/3o72EX5QZ9N9d51dqo/giphy.gif)