Intro
In this article, we wil look at how to use AWS Serverless services to set up a basic One-Time Password (OTP) system, which may be used as part of two-factor authentication.
Let us list the tools and technologies used to build this application.
- AWS Lambda
- API Gateway
- DynamoDB
- Simple Email Service - SES
- Amplify Web Hosting
- VueJS for frontend
- Deploy with AWS SAM
Architecture
How it works
In this scenario, we will use a login form built with VueJS and hosted with Amplify static web hosting.
- After the user enters their email and password, an API endpoint is contacted to perform the "
Generate OTP
" Lambda function, which generates a 6-digit code along with asession id
. - "
Generate OTP
" Lambda will save the code andsession id
into aDynamoDB
table after they are generated. - The API endpoint will then return simply the
session id
as a response. - The table has DynamoDB streams enabled. As a result, once the data is stored, the "Send Email" Lambda function is called.
The "
Send Email
" Lambda function will use theSimple Email Service
(SES) to send an email containing the created code to the specified email address.Meanwhile, once the
session id
is retrieved from the API, a second form is offered to enter the code, which is then emailed to the specified address.When the user enters and submits the code, it will confirm it along with the
session id
using another API gateway endpoint that will proxy to the "Verify OTP
" Lambda function.The Lambda function "
Verify OTP
" queries theDynamoDB
table with the specifiedsession-id
and code and returns success or error results.
Key points/Lessons learned
In this case, I set
DynamoDB
TTL to delete the entries after a certain amount of time to avoid rapidly filling the table. When the TTL expires,DynamoDB
will not destroy your record instantly. It is finally erased, however AWS only guarantees that it will be deleted within 48 hours. As a result, while checking the OTP code, it must take into account the same "expiredAt
" parameter that was used to set the TTL.To conveniently query the required data, I used sessionId + OTP code as a primary key when designing the
DynamoDB
table. So, when testing the code, I query theDynamoDB
table by primary key with this combination.When you use
DynamoDB
stream as a trigger for Lambda, it receives triggers for allDynamoDB
events (for example, insert, delete, and update). So, within the Lambda function, I had to filter out only the INSERT events using the record's "eventName."I used AWS's own
Simple Email Service
(SES) to send emails. To send emails to any address, you must first validate your sending email address. This can be accomplished through a support request.To host the application's
frontend
, I used Amplify static web hosting. I used Amplify capabilities such as auto deploys when theGithub repository
is amended and setting up a custom domain name with a few button clicks.I deployed the backend resources using
AWS SAM
. At the time of deployment, the expiry period of theOTP
and the number of digits in theOTP
code can be set.
How to set up
Prerequisites
- AWS CLI
- AWS SAM CLI
- Set up and verified SES send email address
Backend
1. Clone the repository
git clone https://github.com/pubudusj/simple-otp
2. Run
sam init && sam deploy -g
The stack's backend will be created once you enter your stack details and AWS environment parameters. Take note of the ApiBaseUrl
that is returned (copy it).
Frontend
Copy the
.env.example
into.env
file. Now add theApiBaseUrl
value asVUE_APP_API_BASE_URL
.You can either manually deploy the application to your
Amplify web hosting
environment, or authorize your GitHub repository to do so automatically with every git push.The frontend can be executed locally by navigating to the frontend directory and then running the command
run npm server
.
To Delete the stack
To delete the backend, run the command
sam delete
Demo
Demo version of this application is available at :
Feedback
Your valuable feedback on this project is mostly welcome! I would like you to play around with this and if you have any questions or general comments, please reach out to me via Personal Blog, LinkedIn, Twitter or Github.
Thank you for taking the time to read this! Your valuable feedback on this project is mostly welcome! I would like you to play around with this and if you have any questions or general comments, please reach out to me on LinkedIn and Medium to so we can talk more about it. 😅
Top comments (0)