Lesson 9 / 32
Identity Tokens and Tenant Claims
Read tenant information from verified token claims, know which claims to trust, and avoid client-controlled tenant headers.
By Rahul Agarwal · 15 years in web development
Trust signed claims, not client input
After login, an identity provider usually issues a signed token, often a JWT. Its claims can include the user id (sub), the audience, an expiry, and tenant information such as the active tenant_id or a list of memberships with roles. Because the token is signed, your API can trust claims after verifying the signature, issuer, audience and expiry. Contrast that with an X-Tenant-Id header sent by the browser: anyone can edit it, so on its own it proves nothing. If you accept such a header to let a user switch tenants, treat it only as a request and check it against the verified memberships. Keep tokens small: embedding hundreds of memberships bloats every request, so some systems put only the active tenant in the token and issue a new token when the user switches tenants. Role changes are another reason for short token lifetimes, since a revoked admin keeps their power until the token expires.
A token payload with an active tenant
An illustrative decoded JWT payload. Claim names other than the registered ones (iss, sub, aud, exp) are your own design.
{
"iss": "https://auth.example-saas.com",
"sub": "user_8f21",
"aud": "api.example-saas.com",
"exp": 1767609000,
"tenant_id": "acme",
"role": "admin"
}Gateways may set headers, browsers may not
A common pattern is an API gateway that verifies the token and then forwards a trusted X-Tenant-Id header to internal services. That is safe only if services are unreachable except through the gateway and the gateway strips any incoming copy of that header from clients.
Quick check: Why is a browser-supplied `X-Tenant-Id` header not enough to authorise access to a tenant?
- Headers are limited to 8 characters
- Browsers cannot send custom headers
- The client controls it, so it must be checked against verified memberships
- HTTP/2 drops custom headers
Answer
The client controls it, so it must be checked against verified memberships — Anything the client sends can be forged. Only signed, verified claims or a server-side membership lookup can prove the user belongs to the tenant.