I recently built a prototype web app that performs phone number verification using an event-driven architecture pattern in Node.js on AWS Lambda with AWS Kinesis streams. This might be interesting if you are:
- looking for an example implementation of phone number verification
For learning purposes, code not meant to be used in production! - interested in event-driven microservices
- building serverless (FaaS) functions with AWS Lambda
- using event-driven architecture patterns with AWS Kinesis Streams
Source Code
phone-verification — phone number verification example project on Github
Full-stack Architecture
Front-end Web UI
- a React web app in Javascript
- react-phone-number-input — React component for phone number entry
- Build process: create-react-app, prettier, etc.
Back-end Services
- Node.js
- AWS Lambda Microservices
- Serverless framework
- AWS Kinesis Streams
- AWS DynamoDB
- Plivo SMS Gateway
- AWS S3 + Cloudfront Static Site Hosting
Step-by-step guide to implementation
0. Prerequisites
- AWS Account
- Install and configure the AWS CLI
1. Deploy the web app
- In the AWS Console, configure AWS S3 and AWS Route53 to establish static website hosting using a custom domain — see detailed instructions.
- Setup AWS CloudFront to serve the static website. See Host a Static Site on AWS, using S3 and CloudFront and then establish secure communication between the browser and web server Using HTTPS with CloudFront.
3. Clone, install, build, and deploy the web app.
$ git clone https://github.com/marksoper/phone-verification
$ cd phone-verification
$ cd webapp
$ yarn install
$ yarn build
$ cd build
$ aws s3 cp ./ s3://<your bucket/domain name>/ --recursive
2. Setup the database in DynamoDB
In the AWS console, create a DynamoDB table
Table name: VerificationChallenges
Primary partition key: createdDate (String)
Primary sort key: smsCode (Number)
3. Create a Kinesis Event Stream
In the AWS console, create a Kinesis stream
Table name: phone-verification-event-stream
Number of shards: 1
4. Create an “event log” Log Group in CloudWatch
This is essentially optional. If you don’t want this you’ll need to remove the code in each of the Lambda functions that logs to this CloudWatch Log Group.
Log group name: verificationEventLog
5. Create Three Lambda services with Serverless framework
The send-sms-verification-code Lambda function requires access to the Plivo API. Plivo API account authentication credentials are kept out of version control in a file called config.js. See the instructions in the project README for the expected format of this file.
You should also consider using AWS Lambda’s environment variables feature to make these credentials available. For this size app it probably doesn’t really matter, but for larger projects I would look carefully at both options.
Before creating the Lambda functions, you must edit the serverless.yml file, replacing < region > with your AWS region and < AWS Account ID > with your AWS account ID.
To create all 3 Lambda functions, from the repo root …
$ cd auth
$ serverless deploy -v
This will also create new roles and policies for these Lambda functions.
NOTE — at present Lambda does not support Node.js 7.x, so asyncawait is used to allow async await capability a la es7 in the Lambda functions.
Lambda function — auth-request-verification-code
Once created, test the auth-request-verification-code function in the AWS Console Lambda page by choosing Actions > Configure Test Event and entering input JSON:
{
"httpMethod": "POST",
"body": {
"phoneNumber": "< your testing phone number here >"
}
}
Lambda function — auth-send-sms-verification-code
The Serverless framework covers AWS Lambda definitions and associated roles/policies. But AFAIK it doesn’t deal with Kinesis mappings to those functions. Once both your auth-send-sms-verification-code Lambda function and your Kinesis stream are defined, you’ll need to update your Lambda to be invoked when stream records occur in Kinesis.
$ aws lambda create-event-source-mapping \
— region < enter your region here > \
— function-name auth-send-sms-verification-code \
— event-source < enter your kinesis stream ARN here > \
— starting-position TRIM_HORIZON
Once the mapping is created, it can be tested in the AWS Console using Actions > Configure Test Event OR by running the auth-request-verification-code function and using the CloudWatch logs to debug the flow through Kinesis.
Lambda function — auth-verify-verification-code
{
"httpMethod": "POST",
"body": {
"phoneNumber": "< your testing phone number >",
"verificationCode": "< your verification code >"
}
}
6. Testing
Front-end Web UI
Use standard create-react-app testing methodologies, including unit tests and the local web deployment feature (yarn start) for dev and testing of the web app.
$ cd webapp
$ yarn install
$ npm test
$ yarn start
Lambda Functions
Lambda functions can be tested manually using both the CLI and AWS Console. I used the AWS Console’s Lambda test invoke feature and CloudWatch Logs. A CloudWatch Log Group should be created automatically when you create the Lambda function.
Unit testing is challenging in AWS Lambda. I didn’t write any unit tests for this project. The are important implications on overall code organization — see this Unit testing guide from Serverless for example — that I would pay attention to in larger production projects.
Further Reading
Event-driven microservices
- MapR — Event-driven microservices patterns
- Pivotal — Messaging Patterns for Event-Driven Microservices
Event-driven architecture
- Wikipedia — Event-driven architecture
- Java design patterns — Event-driven architecture
- Evaluating Message Brokers: Kafka vs. Kinesis vs. SQS