AWS Serverless Authenticated API

This project implements a fully serverless, secure backend API on AWS using Amazon Cognito for authentication, API Gateway for routing and authorization, AWS Lambda (Python) for compute, and DynamoDB for persistent NoSQL storage. The entire solution is built using modern cloud-native patterns and reflects real-world microservice architectures used in enterprise environments.


Overview

The API allows authenticated users to create and retrieve items from a DynamoDB table. Authentication and authorization are handled through Amazon Cognito’s Hosted UI, which issues JWT access tokens. These tokens are validated at API Gateway through a Cognito Authorizer before any Lambda function is invoked.

Key AWS Services:

  • Amazon Cognito (User Pool, Hosted UI, OAuth2 Implicit Flow)
  • API Gateway (REST API with JWT Cognito Authorizer)
  • AWS Lambda (Python backend)
  • Amazon DynamoDB (NoSQL table)
  • IAM (execution role permissions and security boundaries)
  • CloudWatch Logs (monitoring)

Architecture Diagram



















Architecture Flow

  1. User signs in through the Cognito Hosted UI.
  2. Cognito returns a JWT access_token to the user.
  3. User calls the API using: Authorization: <access_token>
  4. API Gateway validates the JWT using the Cognito Authorizer.
  5. Lambda executes and processes the request.
  6. DynamoDB stores or retrieves data.
  7. Response is returned to the client.

API Endpoints

GET /items
Returns all items from the DynamoDB table.

POST /items
Creates a new item with a generated UUID, name, and timestamp.


Lambda Function (Python)

The Lambda function processes both GET and POST requests:


import json
import boto3
import uuid
import decimal

dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("YOUR_TABLE_NAME")

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return float(o)
        return super().default(o)

def lambda_handler(event, context):
    method = event.get("httpMethod", "")

    if method == "GET":
        result = table.scan()
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(result["Items"], cls=DecimalEncoder)
        }

    if method == "POST":
        body = json.loads(event["body"])
        item = {
            "id": str(uuid.uuid4()),
            "name": body.get("name", "Unnamed"),
            "timestamp": body.get("timestamp", "N/A")
        }
        table.put_item(Item=item)
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"message": "Item stored", "item": item})
        }

    return {"statusCode": 405, "body": "Method Not Allowed"}
  

DynamoDB Table

  • Primary Key: id (string)
  • Additional attributes stored: name, timestamp
  • Schema-less and scales automatically

Cognito Authentication

  • Hosted UI handles user login
  • OAuth2 flows: Implicit Grant + Auth Code
  • API Gateway requires a valid JWT access token
  • Unauthorized requests return 401 Unauthorized

Issues Encountered & Fixes

1. Hosted UI always returned response_type=code
Fixed by enabling Implicit Grant and setting a Default Redirect URL.

2. DynamoDB AccessDeniedException
Lambda role was missing required permissions. Resolved by adding a least-privilege IAM inline policy granting: dynamodb:PutItem, dynamodb:Scan, dynamodb:GetItem.

3. Using the wrong token type
API Gateway requires the access_token, not the id_token.


Technologies Used

  • Amazon Cognito
  • API Gateway REST API
  • AWS Lambda (Python)
  • Amazon DynamoDB
  • IAM Permissions
  • JWT + OAuth2
  • CloudWatch Logs

What This Project Demonstrates

  • Serverless microservice design
  • Authentication & authorization best practices
  • Building secure REST APIs
  • Event-driven Lambda patterns
  • DynamoDB NoSQL data modeling
  • IAM least-privilege role construction
  • End-to-end cloud application delivery
Previous
Previous

Secure Serverless Web Delivery on AWS (Terraform)

Next
Next

Azure VM Infrastructure & Network Architecture Implementation