Safe User Impersonation for SaaS Support Teams: Consent, Scope and Audit
Founder & Lead Engineer, RAITHub
RAITHub ships and tests production software. See QA as a Service or talk to us.
Build SaaS impersonation so support can see what a customer sees without becoming them: keep the staff member's real identity in the session alongside the impersonated user, scope what impersonation may do (often read-only or no access to money and credentials), time-limit it, show a persistent banner, and write every action to the audit log under the real staff member, not the customer.
This is engineering guidance for multi-tenant SaaS. If you would rather have it built and tested for you, see how RAITHub would build this below.
Why is impersonation so risky if you get it wrong?
Because a naive version replaces the session's user with the customer's, so from that point on the system cannot tell staff from customer. If staff then change a setting or delete data, the audit log blames the customer. If the session leaks, an attacker inherits a staff member's ability to walk into any account. And it is often done with no customer awareness at all. The fix is to never lose the real identity, and to constrain what impersonation can reach.
| Design | Who the system thinks you are | Risk |
|---|---|---|
| Swap the session user | The customer, fully | Audit blames the customer; no limits; no accountability |
| Share the customer's password | The customer | Credential sprawl; impossible to revoke or attribute |
| Dual-identity session | Staff member acting as the customer | Low, if scoped, timed and audited |
How should an impersonation session be modelled?
Keep both identities in the session: the acting staff member and the impersonated user. Authorisation for the customer's data comes from the impersonated user; accountability stays with the staff member. Record each session so it can be reviewed and ended.
// The session carries BOTH identities for the whole impersonation.
interface Session {
userId: string // the impersonated customer (drives data access)
tenantId: string
actingStaffId?: string // set ONLY during impersonation
impersonationId?: string // the impersonation_sessions row
impersonationExpiresAt?: string
scope?: 'read_only' | 'full' // what this impersonation may do
}
// Every write records WHO really did it.
export function actorForAudit(s: Session) {
return s.actingStaffId
? { actorId: s.actingStaffId, actorType: 'staff', onBehalfOf: s.userId }
: { actorId: s.userId, actorType: 'user' }
}
CREATE TABLE impersonation_sessions (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
staff_id uuid NOT NULL REFERENCES users(id), -- the real person
target_id uuid NOT NULL REFERENCES users(id), -- the customer
tenant_id uuid NOT NULL REFERENCES tenants(id),
reason text NOT NULL, -- a support ticket reference
scope text NOT NULL DEFAULT 'read_only',
consent text NOT NULL DEFAULT 'none', -- none | policy | explicit
started_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz NOT NULL, -- short, e.g. 30 minutes
ended_at timestamptz
);
What should impersonation be allowed to do?
Default to read-only, and carve out things no support session should ever reach even when fuller access is granted: viewing or changing passwords and 2FA, reading recovery codes, changing payout details, or taking destructive actions. Scope is enforced in code on every request, not by asking staff to be careful. A time limit is part of the scope: a 30-minute window that cannot be silently extended means a forgotten impersonation session expires on its own.
// A single check all customer-data writes pass through.
export function assertAllowed(session: Session, action: 'read' | 'write' | 'sensitive') {
if (!session.actingStaffId) return // normal user, normal rules
if (new Date(session.impersonationExpiresAt!) < new Date())
throw new Error('impersonation session expired')
if (session.scope === 'read_only' && action !== 'read')
throw new Error('impersonation is read-only')
if (action === 'sensitive')
throw new Error('impersonation cannot perform sensitive actions')
}
Which permissions a staff role may use while impersonating should come from the same permission model as the rest of the product, so it is declared and testable rather than scattered through the code. That model is covered in the SaaS authorization and RBAC design guide.
Does the customer need to know, or consent?
At minimum, make impersonation visible: a persistent banner while it is active ("You are viewing Acme as support agent Dana"), and an option for workspace admins to require explicit customer consent before a session can start. Three honest levels: none (your policy allows support access, disclosed in your terms), policy-based (the customer's plan or admin setting controls whether it is allowed), and explicit (the customer approves each session or a time-boxed window). Enterprise buyers increasingly ask which you offer.
Whether customers can be impersonated without per-session consent, and what you must disclose, depends on your contracts and local law. This is general information; confirm the requirements with your adviser. The engineering job is to make every level possible and to prove, from the audit log, which was used.
How does impersonation stay accountable?
Every action taken during impersonation is written to the audit log under the real staff member, with the impersonated user recorded as "on behalf of", so a later review reads "Dana (support), acting as Acme's owner, exported the customer list". Log the start and end of every session, its reason and scope, and surface a customer-visible history of when support accessed their account. The append-only, tamper-evident design for that log is in the SaaS audit log design guide.
Do-it-yourself estimate: 1–2 weeks for a dual-identity session, scope enforcement, expiry, a banner and audit entries, if you already have an audit log and a permission model. The main risks are a session that loses the real identity (so the audit blames the customer) and a scope that is not enforced on the server.
Buy, build or hire?
| Option | Examples | Choose this when | Watch out for |
|---|---|---|---|
| Auth provider impersonation feature | A hosted auth service with a "login as user" action | You use their sessions and want a quick support login | Scope limits, consent levels and your own audit trail may still be yours |
| A support/session tool | A co-browsing or screen-sharing support tool | You want to see the screen without acting in the account | Different from acting as the user; no changes, but also no write access when needed |
| Custom build on your sessions | The dual-identity design in this guide | Impersonation must follow your roles, scopes, consent and audit | You own scope enforcement, expiry and accountability |
| Hire a team to build it | RAITHub or another studio | Enterprise buyers ask about support access and you want it audited | Get the scope, expiry and audit tests in the handover |
How do you test impersonation?
- Attribution: act during impersonation and assert the audit entry names the staff member, not the customer.
- Scope: in a read-only session, attempt a write and a sensitive action and assert both are refused.
- Expiry: use the session past its window and assert it is rejected and cannot be silently extended.
- Isolation: assert staff can only impersonate within permission, and never reach passwords, 2FA or recovery codes.
- Visibility: assert the banner shows throughout and the customer's access history records the session.
How RAITHub would build this
- Session model: a dual-identity session that keeps the staff member's real identity alongside the impersonated user, with a short, non-extending expiry.
- Scope and consent: read-only by default, hard limits on sensitive actions, and configurable consent levels (none, policy, explicit).
- Accountability: every action audit-logged under the real staff member, a persistent banner, and a customer-visible access history.
- Tests: attribution, scope, expiry and isolation tests in CI.
Timeline: impersonation inside a new SaaS build fits the 4–6 week fixed scope; added to an existing product it is a bounded piece in the 6–12 week backend range. You receive: scope and audit tests in CI, handover docs and runbooks, and full IP under NDA.
Next step: a free 15-minute technical audit, then a written fixed quote. See the SaaS development service, pair it with the audit log design guide, and book the audit.
Frequently asked questions
What is user impersonation in a SaaS?
A support feature that lets staff view and sometimes act in a customer's account to reproduce an issue. Done safely, the staff member's real identity is kept in the session, access is scoped and time-limited, and every action is audit-logged under the staff member.
Should support staff share the customer's password to log in?
No. Sharing passwords creates credential sprawl, cannot be revoked cleanly, and makes every action look like the customer's. Use a dual-identity impersonation session that keeps staff and customer identities separate and attributes actions correctly.
Should impersonation be read-only?
Default to read-only, and block sensitive actions, such as viewing passwords or recovery codes, changing payout details or deleting data, even when fuller access is granted. Enforce the scope on the server for every request, not by trusting staff to be careful.
Do customers have to consent to being impersonated?
It depends on your contracts and local law; confirm with your adviser. Engineering should make every level possible, from disclosed policy access to per-session explicit consent, always show a banner while active, and record which level was used in the audit log.
How do I keep impersonation accountable?
Write every impersonated action to a tamper-evident audit log under the real staff member, with the customer recorded as "on behalf of". Log each session's start, end, reason and scope, and show the customer a history of when support accessed their account.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.