DEV Community

Auth By Example
Auth By Example

Posted on

Pull the tenant from the auth context, not the request body

In multi-tenant apps, a common bug is reading tenant_id from the JSON body or query string and then authorizing against that value.

Anyone can send tenant_id=other-customer. The tenant for an authorization check must come from the authenticated principal or server-side session — the same place you already trust for user identity — not from client-supplied fields.

Pattern:

  1. Authenticate the caller.
  2. Resolve their tenant (or list of tenants) from the token/session/membership store.
  3. Authorize the action for that tenant and resource.
  4. Ignore or reject a client-supplied tenant that does not match the resolved one.

Treat client tenant_id as a filter preference at most, never as proof of tenancy.

Top comments (1)

Collapse
 
srikanth-supero profile image
Srikanth Reddy Kasa •

I agree with the main point. The request body is the obvious place to check, but tenant IDs can also come through query parameters, URL paths, and headers such as X-Tenant-Id. Filtering only the body still leaves several ways to bypass tenant isolation.
One case that’s easy to miss is create or update requests. If a shared input model accepts tenant_id, a caller may be able to create a record under another tenant—or move an existing record into one. The request can succeed normally, so the issue may not appear in logs as an error.
A useful test is to sign in as tenant B and send tenant A’s ID through each possible input: body, query string, path, and headers. Every attempt should be blocked or return no data. Then repeat the same requests as tenant A and confirm they work. That second check matters because an empty response alone doesn’t prove tenant isolation is working; the request itself might simply be invalid.