Course contentsShow
← C#
Lesson 1272 of 1,90811. Identity, Security, and ClaimsFree lesson

Managing Multi-Tenancy Identity Isolation

Ensure absolute data isolation between different tenants in a shared identity store.

In this lesson, you will learn how to enforce strict logical boundaries within a shared identity store to ensure users from one tenant can never access or accidentally interact with the data of another.

The Challenge of Shared Identity Stores

When multiple organizations (tenants) share a single database for identity, the primary risk is "cross-tenant contamination." If your code fetches a user by an ID without verifying their TenantId, a user could potentially manipulate a request to access resources belonging to a competitor. To prevent this, your identity architecture must treat TenantId as a mandatory, immutable component of every identity-related operation.

Enforcing Isolation at the Data Layer

The most robust way to achieve this in C# is by leveraging Global Query Filters in Entity Framework Core. By enforcing a filter on your DbContext, you ensure that the application automatically ignores records that don't belong to the currently authenticated tenant, preventing accidental data leakage.

public class ApplicationDbContext : DbContext
{
    private readonly ITenantProvider _tenantProvider;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Automatically inject the TenantId into every query
        modelBuilder.Entity<User>().HasQueryFilter(u => u.TenantId == _tenantProvider.GetTenantId());
    }
}

Implementing "Identity Scoping"

Beyond database filters, your identity logic must be "tenant-aware." When a user authenticates, their TenantId should be embedded as a custom claim within their security token (JWT).

Once the user is authenticated, do not rely on user-provided input to determine which tenant they belong to. Instead, extract the TenantId directly from the ClaimsPrincipal during every request:

  1. Extraction: Retrieve the TenantId claim from the validated token.
  2. Validation: Ensure the requested resource ID belongs to the extracted TenantId.
  3. Application: If a user attempts to access a resource with a mismatching TenantId, throw an unauthorized exception immediately.

By binding every identity operation to the authenticated TenantId claim, you create a "sandbox" that remains consistent regardless of which service or background process is handling the request.

Key Takeaway: Absolute isolation is achieved by treating the TenantId as an immutable claim within the identity token and enforcing it through both automated query filters and rigorous scope validation on every API request.