Skip to content

mhmdhussein/tenantflow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TenantFlow – Multi-Tenant SaaS Backend (.NET 8)

.NET Architecture Database Tests

TenantFlow is a production-ready, multi-tenant SaaS backend built with ASP.NET Core, Entity Framework Core, and PostgreSQL, following Clean Architecture principles.

It demonstrates how to correctly implement shared-database multi-tenancy, strict tenant isolation, role-based authorization, audit logging, and integration testing in a real-world SaaS system.


✨ Key Features

  • Clean Architecture (API, Application, Domain, Infrastructure)

  • Multi-tenancy using shared database + shared schema

  • Tenant resolution via X-Tenant-ID HTTP header

  • Strict data isolation using TenantId + EF Core global query filters

  • JWT authentication with roles:

    • SuperAdmin
    • TenantAdmin
    • User
  • Tenant lifecycle management (provisioning, deactivation)

  • Audit logging via EF Core SaveChanges interceptor

  • Admin-only audit log querying

  • Background job support with Hangfire

  • PostgreSQL with EF Core migrations

  • Swagger UI secured with JWT + tenant header

  • Dockerized local development

  • Integration tests using Testcontainers + PostgreSQL


🧱 Architecture Overview

TenantFlow follows Clean Architecture, enforcing strict dependency rules:

src/
├── TenantFlow.Api              → HTTP layer (controllers, middleware, auth)
├── TenantFlow.Application      → Use cases, abstractions, DTOs
├── TenantFlow.Domain           → Core business entities and rules
├── TenantFlow.Infrastructure   → EF Core, Identity, multi-tenancy, auditing

Dependency direction

Api → Application → Domain
Api → Infrastructure → Domain
Application → Domain

The Domain layer has zero dependencies on infrastructure or frameworks.

Architecture Diagram

            ┌──────────────────────────────┐
            │          Client              │
            │  (Browser / Mobile / API)    │
            └──────────────┬───────────────┘
                           │
                           │ HTTP + JWT + X-Tenant-ID
                           ▼
┌────────────────────────────────────────────────────┐
│                TenantFlow.Api                      │
│----------------------------------------------------│
│ Controllers                                        │
│ Middleware                                         │
│  • TenantResolutionMiddleware                      │
│  • Authentication / Authorization                  │
│----------------------------------------------------│
│            Application Layer                       │
│----------------------------------------------------│
│ Use Cases / DTOs / Interfaces                      │
│  • ICurrentUser                                    │
│  • ITenantContext                                  │
│  • IJwtTokenService                                │
│----------------------------------------------------│
│                Domain Layer                        │
│----------------------------------------------------│
│ Entities                                           │
│  • Tenant                                          │
│  • TaskItem                                        │
│  • AuditLog                                        │
│ Value Objects & Rules                              │
│----------------------------------------------------│
│            Infrastructure Layer                    │
│----------------------------------------------------│
│ EF Core + PostgreSQL                               │
│ ASP.NET Identity                                   │
│ Audit Interceptors                                 │
│ Hangfire Background Jobs                           │
└────────────────────────────────────────────────────┘
                           │
                           ▼
                PostgreSQL (Shared DB)

🏢 Multi-Tenancy Model

TenantFlow uses a shared database, shared schema approach.

  • All tenant-scoped entities include a TenantId
  • X-Tenant-ID header is required on tenant-scoped requests
  • Tenant is resolved per request via middleware
  • EF Core global query filters enforce isolation automatically
  • No controller or repository manually filters by tenant

This ensures:

  • No accidental cross-tenant access
  • Centralized enforcement
  • Minimal developer error surface

🔐 Authentication & Authorization

  • JWT Bearer authentication

  • Role-based authorization policies:

    • PlatformOnly → SuperAdmin
    • TenantAdminOnly → TenantAdmin or SuperAdmin
  • Tenant membership enforced at request level

  • Deactivated tenants are blocked at middleware level


🧾 Audit Logging

All changes to tenant-scoped entities are automatically logged using an EF Core interceptor.

Each audit log records:

  • Tenant ID
  • Entity name and ID
  • Operation type (Create, Update, Delete)
  • Timestamp
  • Acting user

Audit logs are queryable via admin-only API endpoints.


🧪 Testing Strategy

TenantFlow includes integration tests that run against a real PostgreSQL instance using Testcontainers.

Covered scenarios:

  • Tenant data isolation
  • Role-based authorization
  • Tenant deactivation enforcement
  • Audit log creation
  • Cross-tenant access prevention

This provides high confidence that security and isolation rules work as expected.


🚀 Running the Project (Docker)

Prerequisites

  • Docker
  • Docker Compose
  • .NET 8 SDK (for local development)

1️⃣ Create environment variables

Create a .env file (an .env.example file is provided):

POSTGRES_DB=tenantflow
POSTGRES_USER=tenantflow
POSTGRES_PASSWORD=tenantflow

CONNECTION_STRING=Host=postgres;Port=5432;Database=tenantflow;Username=tenantflow;Password=tenantflow

JWT_ISSUER=TenantFlow
JWT_AUDIENCE=TenantFlow
JWT_KEY=DEV_ONLY_SUPER_SECRET_KEY_CHANGE_ME

2️⃣ Start the application

docker compose up --build

3️⃣ Apply database migrations

dotnet ef database update \
  --project src/TenantFlow.Infrastructure \
  --startup-project src/TenantFlow.Api

4️⃣ Access the API

  • API: http://localhost:8080
  • Swagger UI: http://localhost:8080/swagger

🔎 Swagger Usage

Swagger is configured with:

  • JWT Authorization header
  • X-Tenant-ID header

Steps:

  1. Log in via /api/auth/login
  2. Copy the JWT token
  3. Click Authorize in Swagger
  4. Set X-Tenant-ID for tenant-scoped endpoints

👤 Default Development User

In Development mode only, the app seeds a platform admin:

Email: admin@tenantflow.dev
Password: Admin123!
Role: SuperAdmin

This allows immediate access to platform endpoints and tenant provisioning.


📦 Database Schema (Core Tables)

  • Tenants
  • AspNetUsers, AspNetRoles (ASP.NET Identity)
  • TaskItems
  • AuditLogs

All tenant-scoped tables include TenantId.


🛣️ Roadmap (Future Enhancements)

  • Refresh tokens
  • Role-based permissions (beyond roles)
  • Soft-delete support
  • Correlation IDs for tracing
  • Rate limiting per tenant
  • Background job monitoring per tenant
  • OpenTelemetry support

🎯 Why This Project Exists

TenantFlow was built to demonstrate:

  • Real SaaS backend architecture
  • Secure multi-tenant data isolation
  • Enterprise-grade authorization
  • Testable, maintainable design
  • Production-ready patterns in .NET

📄 License

This project is licensed under the MIT License. You are free to use, modify, and distribute this project with proper attribution.

About

Production-ready multi-tenant SaaS backend built with ASP.NET Core and PostgreSQL

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors