A support agent assigned to one customer shouldn’t be able to open another customer’s account just because both use your SaaS. Tenant isolation means each customer’s data and actions stay separate from every other customer’s, even on shared infrastructure. For user impersonation, that takes two separate checks:
- Actor to target. May this staff member impersonate this user, for this customer, right now?
- Subject to tenant. May this customer user access the tenant, resource and operation in each request?
Most systems implement the second check already, because it’s ordinary multi-tenant authorization. The first is the one that tends to be missing. Teams ask for it regularly. One Keycloak GitHub discussion (opens in a new tab), for example, asks for service providers to impersonate “only their own users”. Your application owns both checks.
Check the assignment before issuing access
Write the policy in plain terms first. For example: active support staff may open read-only sessions for active, ordinary users of customers in their current portfolio; privileged accounts need a separate process.
Then make the code that issues the impersonation credential resolve, on the server:
- The staff identity, from verified authentication state.
- The mapping from that identity to your internal staff record.
- The target user’s canonical account and customer membership.
- The current staff-to-customer assignment, from your source of truth.
- Any excluded targets, the requested scope and approval requirements.
Deny issuance if any of these is missing or ambiguous. An unknown assignment must never mean access to every customer.
A filtered search list makes picking the right customer easier, but it isn’t the check. Repeat the assignment check when you issue the credential, even if a search or approval succeeded earlier, because assignments can change in between.
Devora handles requests, approvals and scoped sessions, and passes the verified staff identity and target (opens in a new tab) to your backend. It doesn’t know your staff-to-customer assignments or enforce them. Devora can route requests to the right approvers, but it doesn’t restrict which customers a member can request. Put the assignment check in your issuance path.
Check the customer’s tenant access on every request
Passing the assignment check doesn’t give the customer, or the agent, any new permissions. An agent assigned to Amber still can’t read Birch’s invoices through an Amber user’s session. Support shouldn’t quietly inherit admin rights to make a diagnostic work, either.
For every protected request:
- Resolve the authenticated customer user.
- Authorize the requested tenant.
- Check resource ownership.
- Apply the customer’s normal permissions.
- Apply the support session’s extra restrictions, such as read-only.
User IDs, tenant IDs, headers and form fields from the browser are selectors, not proof of authorization. Validate them against server-side identity and membership. The scope and security guide (opens in a new tab) explains where Devora’s backend guard fits. It isn’t a replacement for your tenant checks.
If the customer user belongs to several tenants, decide whether the support session is limited to one of them. If it is, store that restriction in trusted server-side session state and check it on every request. Selecting one tenant in the UI doesn’t stop a request for another.
Test it with two agents and two tenants
Set up synthetic data. Agent A is assigned only to Tenant Amber, and Agent B only to Tenant Birch. User Amber belongs only to Amber, and User Birch only to Birch. Both are ordinary members, and sessions are read-only. These are the outcomes to verify:
| Agent | Target | At issuance | Then requests | Expected |
|---|---|---|---|---|
| A | User Amber | Allowed, subject to approval | Read an Amber resource | Allowed if the user’s permissions allow |
| A | User Birch | Denied: not assigned | (no credential) | Denied |
| B | User Amber | Denied: not assigned | (no credential) | Denied |
| B | User Birch | Allowed, subject to approval | Read a Birch resource | Allowed if the user’s permissions allow |
| A | User Amber | Allowed | Read a Birch resource by changing the ID | Denied: tenant boundary |
| B | User Birch | Allowed | Read an Amber resource by changing a tenant header | Denied: tenant boundary |
| A | User Amber | Allowed | Change an Amber resource | Denied: read-only |
| B | User Birch | Allowed | Change an Amber resource | Denied: tenant and read-only |
Add a privileged user in each tenant and confirm that ordinary support can’t get a credential for them. Also try changing the target ID after approval. Issuance should reject the substitution rather than create access for the new target.
Note which layer produced each denial. A write blocked by read-only scope doesn’t prove tenant isolation, so repeat cross-tenant attempts as reads to test that boundary on its own.
Treat reassignment as an access event
An assignment check at issuance shouldn’t become permanent permission. Decide what happens when assignments change mid-session, and who implements it. For strict isolation, re-check eligibility on protected requests and revoke support access when an assignment is removed.
| Change during Agent A’s Amber session | Expected result | Evidence to collect |
|---|---|---|
| A’s Amber assignment removed | Further requests denied | Assignment change and denial timestamps |
| A moved from Amber to Birch | Amber access denied; Birch needs a new approval | Old-session denial and a separate issuance decision |
| User Amber removed from the Amber tenant | Amber resources denied | Membership lookup and denial |
| Session ended with the tab closed | Credential rejected | Revocation record and a direct API call |
| Session ended while a credential was still being issued | The late credential is rejected | Revocation keyed by session ID |
Devora sends your backend a signed termination notice when it ends a session, even with no tab open. Its session lifecycle guide (opens in a new tab) recommends keying revocation by Devora session ID, so a credential issued after termination is refused too. A change in your own staff assignments is a separate event. Devora won’t see it, so connect it to your revocation process yourself.
Document how long assignment data is cached and the longest stale-access window you’ll accept. Then test the next request from a tab that’s already open. A changed label in an admin screen isn’t evidence.
Use the smallest view that answers the ticket
A tenant-scoped support panel or a sanitized fixture often answers the question without opening a customer session. Use it when it’s enough.
When account access is necessary, review the custom session prerequisites (opens in a new tab), shared security responsibilities and the general impersonation checklist. For audit design, continue with recording the agent and the customer in audit logs.
Once someone on your team owns the assignment checks, evaluate Devora in staging using the matrix above. Get engineering and security review and real test results before using it in production.