A comprehensive authentication and authorization ecosystem for Node.js applications
848
A comprehensive authentication and authorization API server built with Domain-Driven Design (DDD) principles, featuring JWT-based authentication, role-based access control, and flexible database support (AWS DynamoDB or PostgreSQL). Designed for serverless deployment with comprehensive test coverage.
This project follows Domain-Driven Design (DDD) principles with clean architecture:
src/
โโโ auth/
โ โโโ domain/ # Business logic and entities
โ โ โโโ User.ts # User entity with business rules
โ โ โโโ UserDomain.ts # Domain services
โ โโโ application/ # Use cases and application services
โ โ โโโ LoginUseCase.ts
โ โ โโโ SignupUseCase.ts
โ โ โโโ ...
โ โโโ infrastructure/ # External concerns (database, etc.)
โ โ โโโ UserRepository.ts # Repository interface
โ โ โโโ DynamoDBUserRepository.ts # DynamoDB implementation
โ โ โโโ PostgresUserRepository.ts # PostgreSQL implementation
โ โ โโโ UserRepositoryFactory.ts # Factory for database selection
โ โโโ api/ # Controllers and routes
โ โโโ AuthController.ts
โ โโโ AdminController.ts
โ โโโ AuthRoutes.ts
โโโ commons/
โ โโโ infrastructure/ # Shared infrastructure components
โ โโโ Datasource.ts # Database configuration and connection
โโโ app.ts # Express app configuration
โโโ server.ts # Development server
โโโ lambda.ts # AWS Lambda handler
The architecture follows these key principles:
# Clone the repository
git clone https://github.com/luismr/heimdall.git
cd heimdall/heimdall-server
# Install dependencies
npm install
# Setup environment variables
cp .env.example .env
โ ๏ธ Important Package Dependency: This project requires the
@luismr/heimdall-middleware-expresspackage from GitHub Packages. Make sure you:
- Have a GitHub personal access token with
read:packagesscope- Configure npm to use GitHub Packages (via
.npmrc)- Set the
GITHUB_TOKENenvironment variable or provide it during Docker build
Create a .env file in the project root:
# Application Configuration
JWT_SECRET=your-super-secret-jwt-key
USERS_TABLE=HeimdallUsers
PORT=4000
NODE_ENV=development
# Signup Protection (required for creating new users)
SIGNUP_ACCESS_TOKEN=your-signup-access-token
SIGNUP_SECRET_TOKEN=your-signup-secret-token
# Database Selection
DB_TYPE=dynamodb # Options: 'dynamodb' or 'postgres'
# AWS Credentials (required for DynamoDB)
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_REGION=us-east-1
# PostgreSQL Configuration (required if DB_TYPE=postgres)
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=heimdall
POSTGRES_PASSWORD=your-secure-password
POSTGRES_DB=heimdall
POSTGRES_SSL=false
โ ๏ธ Important: Always use strong secrets in production environments!
๐ Database Configuration: Set
DB_TYPEto either 'dynamodb' or 'postgres' to choose your database backend. Make sure to configure the corresponding environment variables for your chosen database type.
The system uses the DB_TYPE environment variable to determine which database to use:
DB_TYPE=dynamodb for AWS DynamoDBDB_TYPE=postgres for PostgreSQLMake sure to configure the corresponding environment variables for your chosen database:
USERS_TABLEPOSTGRES_* variablesIf using DynamoDB, ensure your AWS credentials are properly configured and the USERS_TABLE exists in your DynamoDB instance.
# Create DynamoDB table using AWS CLI
aws dynamodb create-table \
--table-name HeimdallUsers \
--attribute-definitions AttributeName=username,AttributeType=S \
--key-schema AttributeName=username,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
If using PostgreSQL, follow these steps:
CREATE DATABASE heimdall;
CREATE USER heimdall WITH ENCRYPTED PASSWORD 'your-secure-password';
GRANT ALL PRIVILEGES ON DATABASE heimdall TO heimdall;
# Run all pending migrations
npm run typeorm:migration:run
# Revert the last applied migration
npm run typeorm:migration:revert
# Create a new empty migration (for development)
npm run typeorm:migration:create -- -n YourMigrationName
# Generate a migration from entity changes (for development)
npm run typeorm:migration:generate -- -n YourMigrationName
The migrations will:
The system will automatically detect which database to use based on your environment configuration:
POSTGRES_HOST is set, PostgreSQL will be usedThe project uses GitHub Packages which requires authentication to access the required @luismr/heimdall-middleware-express package. You'll need a GitHub personal access token with read:packages scope.
# Build the Docker image with GitHub token
docker build -t heimdall-server . --build-arg GITHUB_TOKEN=your_github_token
# Build with a specific tag
docker build -t heimdall-server:1.0.0 . --build-arg GITHUB_TOKEN=your_github_token
# If you have the token in an environment variable
docker build -t heimdall-server . --build-arg GITHUB_TOKEN=${GITHUB_TOKEN}
โ ๏ธ Security Note: The GitHub token is only used during build time and is not included in the final image. The
.npmrcfile is removed after dependency installation.
For automated Docker builds in GitHub Actions, you need to configure the following secrets:
GH_PACKAGES_TOKEN: A GitHub personal access token with read:packages scope for accessing the middleware packageDOCKERHUB_USERNAME: Your Docker Hub usernameDOCKERHUB_TOKEN: Your Docker Hub access token# Run the container
docker run -d \
-p 4000:4000 \
--name heimdall \
--env-file .env \
heimdall-server
# View container logs
docker logs -f heimdall
# Stop the container
docker stop heimdall
# Remove the container
docker rm heimdall
When running with Docker, make sure to:
.env file as described in the Environment Variables section--env-file flagPOSTGRES_HOST is accessible from within the containerFor development with PostgreSQL, you can use this docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "4000:4000"
env_file: .env
depends_on:
- postgres
postgres:
image: postgres:17-alpine
ports:
- "5432:5432"
environment:
POSTGRES_USER: heimdall
POSTGRES_PASSWORD: your-secure-password
POSTGRES_DB: heimdall
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Run with Docker Compose:
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose down
# Start development server with hot reload
npm run dev
# The API will be available at http://localhost:4000
# Start serverless offline
npm run serverless:dev
# The API will be available at http://localhost:4000
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
http://localhost:4000/apihttps://your-api-domain.com/api/signupRegister a new user account. This endpoint requires special authentication tokens to prevent unauthorized user creation.
Headers Required:
X-Access-Token: your-signup-access-token
X-Secret-Token: your-signup-secret-token
Request Body:
{
"username": "johndoe",
"password": "securepassword123"
}
Response:
{
"username": "johndoe",
"roles": ["ROLE_USER"],
"blocked": false
}
Error Responses:
401 Unauthorized: Missing or invalid signup tokens400 Bad Request: Invalid request body or user already exists500 Internal Server Error: Server configuration error (tokens not configured)/loginAuthenticate user and get JWT tokens.
Request:
{
"username": "johndoe",
"password": "securepassword123"
}
Response:
{
"user": {
"username": "johndoe",
"roles": ["ROLE_USER"],
"blocked": false
},
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
/logout ๐Logout user and invalidate refresh token.
Headers:
Authorization: Bearer <access-token>
Request:
{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response:
{
"message": "Logged out successfully"
}
All admin endpoints require ROLE_ADMIN role.
/admin/block ๐๐Block a user account.
Headers:
Authorization: Bearer <admin-access-token>
Content type
Image
Digest
sha256:8f3db1328โฆ
Size
188.8 MB
Last updated
about 1 year ago
docker pull luismachadoreis/heimdall-server