Ravindra BagaleCourses & study guides मराठी Track your progress

Project: Build an OTP Notifier with Lambda, SNS and DynamoDB (Source Code)

UPI and banking apps send a one-time password. You will build a lab OTP API: store a hash in DynamoDB, send via SNS. Prefer email SNS for the free lab — SMS costs money and needs sandbox exit.

What you'll learn in this chapter

  • Request and verify OTP flows
  • Hash + expiry in DynamoDB
  • SNS email (or careful SMS)
  • Cost warnings and cleanup

1. Everyday example

Why do we need this?

Login without password for a minute: send 6 digits, user types them back. You must expire them fast and never store the raw OTP in plain text.

What is it?

POST /otp/request and POST /otp/verify. Lambda makes a 6-digit code, stores sha256(dest:otp) + expiresAt, publishes SNS.

Cost and sandbox

SNS SMS is billed per message and often starts in an SMS sandbox. For class, subscribe your email to an SNS topic and keep SMS_MODE off.

Download: otp-notifier.zip

2. Lab

How to do it (step by step)

A. Table + topic

  1. DynamoDB yourname-otps, PK dest String.
  2. SNS topic + email subscription (confirm). Copy TOPIC_ARN.

B. Lambda + API

  1. Role: logs + PutItem/GetItem + sns:Publish.
  2. Function handler.py. Env TABLE_NAME, TOPIC_ARN. Do not set SMS_MODE=1 unless you accept SMS cost.
  3. HTTP API routes POST /otp/request and POST /otp/verify. CORS *.
curl -s -X POST "$API_BASE/otp/request" -H 'content-type: application/json' \
  -d '{"dest":"you@example.com"}'
# read OTP from email, then:
curl -s -X POST "$API_BASE/otp/verify" -H 'content-type: application/json' \
  -d '{"dest":"you@example.com","otp":"123456"}'

Cleanup

  1. Delete API, Lambda, table, topic, role. Delete OTP rows if any remain.
  2. If you enabled SMS, disable spend limits experiments and delete sandbox numbers you added.

3. Interview

Q. Why hash the OTP?

DB leak should not reveal usable codes.

Q. Why expiry?

OTPs are short-lived secrets; 5 minutes is common.

Q. SMS vs email lab?

Email SNS avoids SMS cost/sandbox for learning the flow.

Q. Rate limiting?

API GW usage plan or per-dest counters — out of lab scope but interview gold.

Q. Cleanup?

API, Lambda, table, topic.

Try at home

  1. Add attempt counter; lock after 5 fails.
  2. Use DynamoDB TTL on expiresAt.

In short

  1. OTP API = request + verify + hash + SNS.
  2. Prefer email in class.
  3. Never log raw OTP.
  4. Clean up.

Practice Tasks

About this scenario

Stockholm Games is a gaming business in Stockholm. Erik Lindqvist looks after its IT and cloud work. They count money in SEK and run their AWS resources in the eu-north-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 12

Easy List functions

Why: See which functions exist in this Region.

What to do: List the Lambda functions in eu-north-1.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Invoke a function

Why: Invoke runs the function now and saves its answer in a file.

What to do: Invoke sthlmgames-orders-fn and save the response to out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Trust policy for a Lambda role

Why: The trust policy says WHO may take the role.

What to do: Write a trust policy that lets lambda.amazonaws.com assume the role.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Put an item

Why: DynamoDB JSON shows the type of each value: S for string, N for number.

What to do: Put an item into sthlmgames-orders with orderId "o-101" (string) and amount 2500 (number).

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Change timeout and memory

Why: More memory also gives more CPU; timeout stops runaway runs.

What to do: Set sthlmgames-orders-fn to timeout 30 seconds and memory 512 MB.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Let a function write logs

Why: Without these actions, Lambda logs never appear in CloudWatch.

What to do: Allow logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents on arn:aws:logs:*:*:* only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Hard Create a Lambda function

Why: Lambda needs the code zip, a runtime, a handler name and an execution role.

What to do: Create function sthlmgames-orders-fn: runtime python3.12, handler app.handler, role arn:aws:iam::124495484726:role/lambda-basic, code in function.zip.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Set environment variables

Why: Keep settings like table names out of the code.

What to do: Set the environment variable TABLE=sthlmgames-orders on sthlmgames-orders-fn.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Invoke with a JSON payload

Why: In CLI v2, raw JSON needs --cli-binary-format raw-in-base64-out.

What to do: Invoke sthlmgames-orders-fn with payload {"orderId":"o-101"} (raw JSON) and save the reply in out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Lambda GB-seconds

Why: Lambda bills memory × time.

What to do: 1,000,000 invocations, 512 MB memory, 200 ms each. How many GB-seconds?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Hard Connect an SQS queue to Lambda

Why: An event source mapping makes Lambda poll the queue and process messages in batches.

What to do: Create an event source mapping from queue arn:aws:sqs:eu-north-1:124495484726:sthlmgames-orders to sthlmgames-orders-fn with batch size 10.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Let S3 call your function

Why: A resource-based permission is needed before S3 can invoke the function.

What to do: Add permission statement s3invoke to sthlmgames-orders-fn so s3.amazonaws.com can call lambda:InvokeFunction from bucket arn:aws:s3:::sthlmgames-uploads.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

Revision card: OTP notifier with SNS. UPI and banking apps send a one-time password for a minute of trust. You must expire it and not store it in plain text. POST /otp/request creates a 6-digit code, stores sha256(dest:otp) + expiresAt in DynamoDB, publishes via SNS. POST /otp/verify checks the hash. Table PK dest, SNS email topic (prefer email in class), Lambda Put/Get + Publish, routes request and verify. curl request to you@example.com → email has 6 digits → curl verify returns {"ok":true}.
Revision card: OTP notifier with SNS · Download PNG · Open card page
Revision card: Hash and expire OTPs. A DynamoDB leak of raw OTPs lets attackers log in. Forever-valid codes are worse. Store only a hash (e.g. sha256 of dest + otp). Store expiresAt as Unix epoch seconds. Reject after expiry. Generate secrets.token_hex / random 6 digits → hashlib.sha256 → PutItem → never log the raw otp. After 5 minutes verify returns false even with the correct old digits.
Revision card: Hash and expire OTPs · Download PNG · Open card page
Revision card: SNS email vs SMS cost. SMS is billed per message and often starts in an SNS SMS sandbox. A class lab can burn money by accident. For learning the flow, subscribe your email to an SNS topic and keep SMS_MODE off. Production SMS needs spend limits and sandbox exit. Create topic → email subscription → confirm → TOPIC_ARN in env. Do not set SMS_MODE=1 unless you accept SMS charges. Ten students each request one OTP → ten emails, no SMS line on the bill.
Revision card: SNS email vs SMS cost · Download PNG · Open card page
Comparison: SNS email OTP vs SNS SMS OTP. SNS email OTP: Free-tier friendly; confirm subscription once. SNS SMS OTP: Per-message cost; SMS sandbox hurdles.
Comparison: SNS email OTP vs SNS SMS OTP · Download PNG · Open card page
Interview card: Why store a hash of the OTP?. A database leak must not reveal usable login codes. Hashes are one-way; verification re-hashes the user input and compares. sha256(f"{dest}:{otp}") stored with expiresAt; never log the raw digits.
Interview card: Why store a hash of the OTP? · Download PNG · Open card page
Interview card: Why prefer SNS email in the class lab?. SMS costs per message and often needs leaving the SMS sandbox. Email subscriptions teach the same publish/subscribe flow without surprise charges. Keep SMS_MODE unset; confirm email on the topic before requesting OTPs.
Interview card: Why prefer SNS email in the class lab? · Download PNG · Open card page

More cards: Ravi Sir's Cards.