Below is a comprehensive README for this project. Feel free to modify any sections as needed for your specific requirements.
This repository contains a Go-based AWS CDK project that deploys:
- A DynamoDB table for user data
- A Lambda function (written in Go) providing a simple user registration and login flow
- An API Gateway exposing three routes:
- POST /register
- POST /login
- GET /protected
Users can register, log in, and then call the protected endpoint by including a JWT in the Authorization
header.
- Project Structure
- Architecture Overview
- Prerequisites
- Setup & Installation
- Build & Deploy
- Testing the Application
- API Endpoints
- Implementation Details
- Local Development Notes
- Contributing
- License
└── sibteali786-goCdk/
├── go.mod # Root Go module definition
├── go.sum
├── cdk.json # CDK configuration
├── go_cdk.go # Main CDK stack file
├── go_cdk_test.go # CDK tests (optional, commented out for reference)
├── README.md # This README
├── lambda/
│ ├── main.go # Lambda entry point (switches by path)
│ ├── app/
│ │ └── app.go # Constructs the app with DB + API handler
│ ├── api/
│ │ └── api.go # Handlers for /register and /login
│ ├── middleware/
│ │ └── middleware.go # JWT validation middleware
│ ├── database/
│ │ └── database.go # DynamoDB-based user store
│ ├── types/
│ │ └── types.go # RegisterUser, User, JWT creation, password hash check
│ ├── function.zip # Zipped Lambda artifact after `make build`
│ ├── makefile # Makefile to build and zip the Lambda code
│ ├── go.mod # Lambda-specific Go module definition
│ └── go.sum
└── ...
-
AWS Lambda
- Handles requests from API Gateway.
- Written in Go.
- Handles user registration, login (JWT creation), and protected route authorization checks.
-
Amazon DynamoDB
- Stores user information in a table named
userTable
. - Partition key:
username
(string).
- Stores user information in a table named
-
Amazon API Gateway
- Routes traffic to the Lambda function.
- Three main paths:
/register
(POST)/login
(POST)/protected
(GET)
-
JWT Security
- The
/protected
route validates a JWT sent in theAuthorization
header. - Tokens expire after 1 hour.
- Token secret is currently hard-coded as
"secret"
(for demonstration only!).
- The
-
AWS Account: You need an AWS account with permissions to create and manage:
- AWS Lambda
- DynamoDB
- API Gateway
- IAM Roles/Policies
-
AWS CLI:
- Install AWS CLI if you haven’t already.
- Configure it (
aws configure
) with valid credentials.
-
CDK CLI:
- Install AWS CDK.
- Confirm installation with
cdk --version
.
-
Go (1.18+ recommended):
- Download and install Go.
- Verify with
go version
.
-
GNU Make:
- Needed to run the
make build
command in thelambda/
folder.
- Needed to run the
-
Clone the Repository
git clone https://github.com/your-repo/sibteali786-goCdk.git cd sibteali786-goCdk
-
Install Dependencies
- At the root:
go mod download
- In the
lambda/
directory:cd lambda go mod download cd ..
- At the root:
-
Build the Lambda
From thelambda/
directory, run:make build
This will:
- Compile a Linux AMD64 Go binary named
bootstrap
. - Zip it into
function.zip
.
- Compile a Linux AMD64 Go binary named
-
Synthesize the CDK Stack
Return to the project root, run:cdk synth
This generates the CloudFormation template in the
cdk.out/
folder. -
Deploy to AWS
cdk deploy
When prompted, type
y
oryes
to allow IAM roles/permissions creation.
Note: If you have multiple AWS profiles, you may specify
cdk deploy --profile <profile>
.
After deployment, CDK will output your API Gateway endpoint, for example:
https://<random>.execute-api.<region>.amazonaws.com/prod/
You can test using curl or Postman:
-
Register
curl -X POST \ -H "Content-Type: application/json" \ -d '{"username":"alice", "password":"mypassword"}' \ https://<api-url>/register
Responses:
200 OK
– Successfully Registered400 Bad Request
– Invalid/empty fields409 Conflict
– User already exists
-
Login
curl -X POST \ -H "Content-Type: application/json" \ -d '{"username":"alice", "password":"mypassword"}' \ https://<api-url>/login
Responses:
200 OK
– Returns JSON like{"access_token": "<JWT_TOKEN>"}
400 Bad Request
– Invalid user credentials500 Internal Server Error
– DynamoDB or other internal error
-
Protected
curl -X GET \ -H "Authorization: Bearer <JWT_TOKEN>" \ https://<api-url>/protected
Responses:
200 OK
–"This is protected path"
401 Unauthorized
– Missing or invalid token, or token expired
Method | Path | Description |
---|---|---|
POST | /register |
Register a new user. Body: {"username": "...", "password": "..."} |
POST | /login |
Authenticate an existing user and receive a JWT. Body: {"username": "...", "password": "..."} |
GET | /protected |
Access a protected resource, must include Bearer <JWT> in Authorization header. |
-
main.go
- The entry point for the Lambda.
- Imports
app.NewApp()
, which creates anApiHandler
with DB references. - Uses a
switch
statement to route incoming requests based onrequest.Path
:/register
→RegisterUserHandler
/login
→LoginUser
/protected
→ValidateJWTMiddleware(ProtectedHandler)
-
api/api.go
RegisterUserHandler
:- Parses incoming JSON into
RegisterUser
struct. - Checks if user exists; if not, hashes password and inserts in DynamoDB.
- Returns success or relevant error.
- Parses incoming JSON into
LoginUser
:- Parses credentials.
- Verifies password.
- Creates a JWT token and returns to client.
database/database.go
- Manages a DynamoDB client via the AWS SDK for Go.
DoesUserExist(username string) (bool, error)
: Returns whether a user item exists.InsertUser(user types.User) error
: Inserts a new user record (hashed password).GetUser(username string) (types.User, error)
: Retrieves the user record.
middleware/middleware.go
ValidateJWTMiddleware
:- Extracts the token from the
Authorization: Bearer <token>
header. - Parses and validates the token signature and expiry.
- If invalid/expired, returns
401 Unauthorized
. - Otherwise, calls the next handler (
ProtectedHandler
).
- Extracts the token from the
-
Offline Testing
- While AWS SAM or LocalStack can be used, this project is currently set up to run directly in AWS.
- If you need local development, consider refactoring to use SAM or a local DynamoDB instance.
-
Secrets
- The JWT secret is hard-coded as
"secret"
intypes/types.go
. In production, store secrets in:- AWS Secrets Manager, or
- AWS SSM Parameter Store
- Then retrieve the secret at runtime instead of hard-coding.
- The JWT secret is hard-coded as
-
Logging
- The project uses standard logs in CloudWatch (via the Lambda function logs).
- Expand logging as needed to meet your requirements.
- Fork the repository.
- Create a new feature branch.
- Commit your changes.
- Push to your branch.
- Submit a Pull Request.
All contributions are welcome!
This project is licensed under the MIT License. See the LICENSE file for details.
Enjoy building and deploying your serverless authentication API with Go and AWS CDK!