This project is a sample authentication system. It strictly follows a Hexagonal Architecture (Ports and Adapters) pattern to ensure the core domain remains decoupled from external dependencies.
- src/core: The heart of the application, completely isolated from external frameworks.
- entities: Domain models and core business logic.
- usecases: Business use case implementations.
- driver: Inbound ports (interfaces) that define how the outside world interacts with the core.
- driven: Outbound ports (interfaces) that define how the core interacts with the outside world.
- services: Reusable domain services.
- src/adapters: Infrastructure implementations.
- inbound: Driving adapters (e.g., Express controllers, REST routes) that invoke driver ports.
- outbound: Driven adapters (e.g., Database repositories, Cache clients) that implement driven ports.
- User login with email+password at
POST /loginand server response with JWT token - User can set 1 or more strategies of authentication factor at
POST /mfa. Nowadays we have Email/Phone/TOTP - User will be asked to validate at
POST /mfa/validate:- Email: will be sent an email with a code to validate
- Phone: will be sent an SMS/WhatsApp with a code to validate
- TOTP: will show a QR code
- User logout at
POST /logout - Next time the user login, will be sent a list of strategy that is already validated
- User chooses one of strategy sent before at
POST /mfa/choose - User will receive a code of 6 number according to the strategy chosen (TOTP skip this step)
- User will be asked for the code at
POST /mfa/code - User can reset password:
- Send email at
POST /password/forget - Check email with a link (containing a hash)
- Send the new password and hash at
POST /password/recover
- Send email at
- User can create an organization at
POST /organization - User can add another user to an organization at
POST /organization/add - User updates an organization at
PATCH /organization/add
- Can create a user at
POST /user - Can update a user at
PATCH /user
- Created at
POST /loginorPOST /mfa/code - User has 1h to interact with any protected endpoint before token expire
- Refresh at
GET /login/refresh/:token- Token is invalidated and a new one is returned
- Cannot refresh if token is already invalid or expired
- Invalidate token when logout by adding to cache
- Docker v4.9.3
- Docker Compose v5.1.4
- Node v24.10
# rise/destroy all dependency
make infra/up # already create tables based on ./db/migration folder
make infra/down # does not remove volume
make reset # destroy, rise dependencies, and run migrations
# make test on the same condition where it's executed on CI
make ci
make test/mutation # Run Stryker mutation testing
make test/load # Run k6 load testing (requires make start)
# developer and test enviroment
make start # Build and start the API
make dev # start dependencies and open shell in API container
# clean artifacts
make clean/node # node_modules folder and package-lock remove- Security: The API uses
helmetfor HTTP header security, restricted CORS, and disablesx-powered-by. - Telemetry: Instrumented with OpenTelemetry, exporting traces and metrics to a collector (e.g., Uptrace) via
docker-compose.
- Add decorator to inject dependencies instead of layer management
