# Multi-Tenant Isolation — Authentication & Authorization

Source: https://www.skillbyai.com/en/authentication/z-tenant

> Keeping customers' data apart.

## Tenant context everywhere

In a multi-tenant SaaS, a missing tenant filter can leak one customer's data to another. Derive the **tenant ID from the authenticated identity** (session or verified token claim), never from a request parameter the client can change. Isolation options range from **separate databases** (strongest, costly) to **separate schemas** to **shared tables with a tenant column**. With shared tables, add a safety net such as PostgreSQL **row-level security (RLS)**, which filters rows by a per-connection setting even if application code forgets a `WHERE` clause. Apply tenant scoping to caches, search indexes, file storage paths, background jobs and logs too, and be explicit about cross-tenant admin access with extra auditing.

## Row-level security as a backstop

PostgreSQL; the app sets the tenant for each transaction from the verified identity.

```sql
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON invoices
  USING (tenant_id = current_setting('app.tenant_id')::uuid)
  WITH CHECK (tenant_id = current_setting('app.tenant_id')::uuid);

-- per request, inside a transaction, using the tenant from the session or token:
BEGIN;
SELECT set_config('app.tenant_id', '6f1c2b0e-9a1d-4c3e-8f00-1b2c3d4e5f60', true); -- true = local to this transaction
SELECT * FROM invoices WHERE id = 42;  -- returns nothing if it belongs to another tenant
COMMIT;
```

## RLS has bypasses

Table owners and superusers bypass RLS unless you use FORCE ROW LEVEL SECURITY and a non-owner application role. Check the PostgreSQL docs for your version and test isolation explicitly.

**Quiz:** Where should an API take the current tenant ID from?

- [ ] A tenant_id query parameter
- [x] The authenticated session or verified token
- [ ] The Referer header
- [ ] A value in localStorage

*Answer:* The authenticated session or verified token. Client-controlled values can be changed to another tenant's ID.
