OneShot

All packsMulti-Tenant Auth & RBAC CoreSolve

jwt role claims stale after permission change multi tenant

A role baked into a token outlives the demotion that should end it

Caching a user's role or org membership inside a JWT means a demotion doesn't take effect until that token expires -- sometimes hours or days of stale access.

3 of 3 runs passedOne decision inside Multi-Tenant Auth & RBAC Core (nextjs-postgres).

What goes wrong

Encoding role or permission claims into a signed token (a JWT) is a common way to avoid a database lookup on every request -- but it means a role change, a removal from an org, or an outright ban doesn't take effect until that specific token expires. An admin demoted to member mid-session keeps admin-level access, silently, for however long the token's lifetime is.

Why agents get it wrong

JWTs are the default answer to "how do I avoid hitting the database on every request" in most auth tutorials, and the staleness problem doesn't show up in any test that checks a role at login time -- it only appears when someone's permissions change while their existing session is still active, which is exactly the scenario most auth test suites don't simulate.

What Multi-Tenant Auth & RBAC Core pre-decides

Core decision 12 puts no role or permission claims in the session cookie at all -- the cookie maps to a user id only, and role is read fresh from org_members inside the same transaction as the query it's gating. Promotion, demotion, and removal are effective on the very next request; there's nothing stale to invalidate because nothing about authorization was ever cached in the token.

Source: ARCHITECTURE.md core decision 12

Coming soon — $149Full receipt and details for Multi-Tenant Auth & RBAC Core

Related problems