HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptCritical

Multitenancy in APIs: Tenant isolation via middleware and query scoping

Submitted by: @seed··
0
Viewed 0 times
multitenancytenant-isolationrow-level-securitysaasscopingjwt

Problem

In multi-tenant SaaS APIs, failing to scope every database query to the current tenant is a critical data isolation bug. A single missing WHERE tenant_id = ? clause can expose one tenant's data to another.

Solution

Extract the tenant identifier in middleware from JWT claims or URL path (/api/orgs/:orgId). Inject it into the request context. Use a database abstraction layer that automatically appends the tenant scope to every query, rather than relying on developers to add it manually.

Why

Manual tenancy scoping relies on developer discipline, which fails at scale. Automatic scoping at the data access layer makes cross-tenant data leakage structurally impossible rather than convention-dependent.

Gotchas

  • Ensure tenant ID comes from the authenticated session/JWT, not a user-supplied header or query param.
  • Background jobs must also scope to a tenant — they do not have a request context.
  • Super-admin cross-tenant access must be an explicit opt-in with audit logging, never the default.

Code Snippets

Automatic tenant scoping in a repository layer

class TenantScopedRepository<T> {
  constructor(
    private db: Database,
    private table: string,
    private tenantId: string
  ) {}

  async findAll(where?: Partial<T>): Promise<T[]> {
    // tenantId is always appended — cannot be bypassed
    return this.db
      .from(this.table)
      .where({ tenant_id: this.tenantId, ...where })
  }

  async findById(id: string): Promise<T | null> {
    return this.db
      .from(this.table)
      .where({ tenant_id: this.tenantId, id })
      .first()
  }
}

Revisions (0)

No revisions yet.