A modern, production-ready microservice for user authentication and management built with Go, AWS Lambda, and DynamoDB. This service implements Clean Architecture principles, providing JWT-based authentication with comprehensive security features.
- JWT Authentication: Secure token-based authentication with configurable expiration
- User Management: Complete user lifecycle (register, login, profile retrieval)
- Clean Architecture: Layered architecture with separated concerns and dependency injection
- Production Ready: Comprehensive test coverage, CI/CD pipelines, and Docker support
- AWS Native: Built for AWS Lambda with DynamoDB integration
- Security First: Password hashing, input validation, and secure JWT handling
- Observable: Structured logging with request tracing
- Scalable: Serverless architecture with automatic scaling
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/prod/users/register |
Register a new user | ❌ |
POST |
/prod/users/login |
Authenticate user and get JWT token | ❌ |
GET |
/prod/users/me |
Get current user profile | ✅ |
POST |
/prod/users/{id} |
Get user profile by ID | ❌ |
Register a new user with email validation and password hashing.
Request:
{
"name": "John Doe",
"email": "john@example.com",
"password": "SecurePass123!"
}Response (201 Created):
{
"user_id": 1,
"name": "John Doe",
"email": "john@example.com"
}Error Responses:
400 Bad Request: Invalid input or validation errors409 Conflict: Email already registered
Authenticate user credentials and receive a JWT token.
Request:
{
"email": "john@example.com",
"password": "SecurePass123!"
}Response (200 OK):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Error Responses:
400 Bad Request: Invalid input401 Unauthorized: Invalid credentials
Retrieve current user profile information.
Headers:
Authorization: Bearer <jwt-token>
Response (200 OK):
{
"user_id": 1,
"name": "John Doe",
"email": "john@example.com"
}Error Responses:
401 Unauthorized: Missing or invalid token404 Not Found: User not found
Retrieve user profile information by user ID. This is a public endpoint that doesn't require authentication.
Parameters:
id(path parameter): User ID (integer)
Response (200 OK):
{
"user_id": 1,
"name": "John Doe",
"email": "john@example.com"
}Error Responses:
400 Bad Request: Invalid user ID format404 Not Found: User not found
┌─────────────────────────────────────────────────────────────┐
│ cmd/api (Entry Point) │
├─────────────────────────────────────────────────────────────┤
│ internal/adapter/ │ internal/adapter/ │
│ controller/ │ presenter/ │
│ (Controller Pattern) │ (Response Formatting) │
├─────────────────────────────────────────────────────────────┤
│ internal/core/usecase/ │
│ (Business Logic) │
├─────────────────────────────────────────────────────────────┤
│ internal/core/domain/ │ internal/core/dto/ │
│ (Entities) │ (Data Transfer Objects) │
├─────────────────────────────────────────────────────────────┤
│ internal/core/port/ │
│ (Interface Definitions) │
├─────────────────────────────────────────────────────────────┤
│ internal/infrastructure/ │
│ (External Dependencies: Database, Auth, Config) │
└─────────────────────────────────────────────────────────────┘
├── cmd/api/ # Application entry point
│ └── main.go # Lambda handler setup
├── internal/
│ ├── adapter/ # External interface adapters
│ │ ├── controller/ # Controller Pattern
│ │ │ ├── user_controller.go
│ │ │ └── user_controller_test.go
│ │ └── presenter/ # Response formatting
│ │ └── json_presenter.go
│ ├── core/ # Business logic layer
│ │ ├── domain/ # Domain entities
│ │ │ └── user.go
│ │ ├── dto/ # Data transfer objects
│ │ │ └── user_dto.go
│ │ ├── port/ # Interface definitions
│ │ │ ├── mocks/ # Generated test mocks
│ │ │ ├── jwt_signer_port.go
│ │ │ ├── presenter_port.go
│ │ │ ├── user_controller_port.go
│ │ │ ├── user_repository_port.go
│ │ │ └── user_usecase_port.go
│ │ └── usecase/ # Business use cases
│ │ ├── user_usecase.go
│ │ ├── user_usecase_test.go
│ │ └── user_usecase_suite_test.go
│ └── infrastructure/ # Infrastructure layer
│ ├── auth/ # JWT implementation
│ │ └── jwt.go
│ ├── config/ # Configuration management
│ │ └── config.go
│ ├── datasource/ # Database implementation
│ │ └── dynamodb_user_repository.go
│ └── logger/ # Logging utilities
│ ├── logger.go
│ └── pretty_handler.go
├── .github/workflows/ # CI/CD pipelines
├── dist/ # Build artifacts (generated)
├── Dockerfile # Multi-stage container build
├── Makefile # Build automation
├── go.mod # Go module definition
└── *.json # AWS resource templates
- Language: Go 1.25
- Runtime: AWS Lambda (Custom Runtime)
- Database: Amazon DynamoDB
- Authentication: JWT with HMAC-SHA256
- Security: bcrypt password hashing
- Testing: Go testing with testify and gomock
- CI/CD: GitHub Actions
- Containerization: Docker with multi-stage builds
github.com/aws/aws-lambda-go- AWS Lambda runtimegithub.com/aws/aws-sdk-go-v2- AWS SDK v2github.com/golang-jwt/jwt/v5- JWT implementationgolang.org/x/crypto- Cryptographic functions
github.com/stretchr/testify- Testing frameworkgo.uber.org/mock- Mock generationgithub.com/fatih/color- Colored output for development
| Variable | Description | Example | Required |
|---|---|---|---|
USERS_TABLE_NAME |
DynamoDB users table name | hackathon-users |
✅ |
IDS_TABLE_NAME |
DynamoDB ID sequence table | hackathon-ids |
✅ |
AWS_REGION |
AWS region | us-east-1 |
✅ |
JWT_SECRET |
HMAC secret for JWT signing | your-256-bit-secret |
✅ |
JWT_EXPIRATION |
Token expiration duration | 24h |
✅ |
JWT_SECRET=your-secure-256-bit-secret-here
AWS_REGION=us-east-1
USERS_TABLE_NAME=hackathon-users-local
IDS_TABLE_NAME=hackathon-ids-local
JWT_EXPIRATION=24h- Go 1.25 or later
- AWS CLI configured
- Make (for build automation)
- Docker (optional, for containerized builds)
-
Clone and setup:
git clone https://github.com/FIAP-SOAT-G20/hackathon-user-lambda.git cd hackathon-user-lambda cp .env.example .env # Configure your environment
-
Install dependencies:
go mod download
-
Generate mocks for testing:
make mock
-
Run tests:
make test # Run all tests make coverage # Run tests with coverage report
-
Build for deployment:
make build # Build Linux binary make package # Create deployment package
| Command | Description |
|---|---|
make build |
Build Lambda binary for Linux |
make package |
Create ZIP deployment package |
make test |
Run all tests with race detection |
make coverage |
Generate test coverage report |
make mock |
Generate mocks for interfaces |
make fmt |
Format Go code |
make clean |
Clean build artifacts |
-
Build the deployment package:
make package
-
Deploy using AWS CLI:
aws lambda create-function \ --function-name hackathon-user-service \ --runtime provided.al2023 \ --role arn:aws:iam::ACCOUNT:role/lambda-execution-role \ --handler bootstrap \ --zip-file fileb://dist/function.zip \ --environment Variables='{ "USERS_TABLE_NAME":"hackathon-users", "IDS_TABLE_NAME":"hackathon-ids", "AWS_REGION":"us-east-1", "JWT_SECRET":"your-secret", "JWT_EXPIRATION":"24h" }'
-
Update existing function:
aws lambda update-function-code \ --function-name hackathon-user-service \ --zip-file fileb://dist/function.zip
# Build Docker image
docker build -t hackathon-user-service .
# Run locally for testing
docker run -p 8080:8080 \
-e USERS_TABLE_NAME=users \
-e IDS_TABLE_NAME=ids \
-e JWT_SECRET=test-secret \
hackathon-user-serviceCreate required DynamoDB tables:
Users Table:
{
"TableName": "hackathon-users",
"KeySchema": [
{
"AttributeName": "userId",
"KeyType": "HASH"
}
],
"AttributeDefinitions": [
{
"AttributeName": "userId",
"AttributeType": "N"
},
{
"AttributeName": "email",
"AttributeType": "S"
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "email_index",
"KeySchema": [
{
"AttributeName": "email",
"KeyType": "HASH"
}
],
"Projection": {
"ProjectionType": "ALL"
}
}
]
}IDs Table:
{
"TableName": "hackathon-ids",
"KeySchema": [
{
"AttributeName": "sequence",
"KeyType": "HASH"
}
],
"AttributeDefinitions": [
{
"AttributeName": "sequence",
"AttributeType": "S"
}
]
}The project includes comprehensive GitHub Actions workflows:
- Unit Tests: Automated testing with Go 1.25
- Test Coverage: Comprehensive test coverage reporting
- Security Scanning: Vulnerability detection with govulncheck
- Linting: Code quality checks with golangci-lint
- Build & Deploy: Automated Docker builds and ECR pushes
Workflows are triggered on pull requests and main branch pushes.
The project maintains high test coverage with comprehensive test suites:
- Unit Tests: Business logic and use case testing
- Integration Tests: End-to-end API testing
- Mock Tests: Interface contract verification
# Run all tests
make test
# Run with coverage
make coverage
# Run specific test package
go test ./internal/core/usecase/...
# Run with verbose output
go test -v ./internal/...- Password Security: bcrypt hashing with salt
- JWT Security: HMAC-SHA256 signing with configurable expiration
- Input Validation: Comprehensive request validation
- Dependency Scanning: Automated vulnerability detection
- Secure Headers: Standard security headers in responses
- Serverless: Auto-scaling with AWS Lambda
- Optimized Builds: Minimal binary size with build optimizations
- Connection Pooling: Efficient DynamoDB connection management
- Structured Logging: Minimal performance impact logging
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Go best practices and idioms
- Maintain test coverage above 80%
- Use conventional commit messages
- Ensure all CI checks pass
This project is licensed under the MIT License - see the LICENSE file for details.
FIAP SOAT G20 - Hackathon User Service Team
Built with ❤️ using Go and AWS serverless technologies.