Impersonate a customer for support
Use impersonation when a customer reports a bug you can’t reproduce from your own account — a missing charger in their list, a stuck session, a tariff that looks wrong on their receipt. Impersonation lets you load the customer surface scoped to their user, with every request you make written to the impersonation audit trail.
Prerequisites
Section titled “Prerequisites”- Your account has
role = admin. - You are not already impersonating another customer. The start endpoint refuses a second impersonation until the first ends.
- You have the customer’s Public ID or their email — enough to locate them in Admin → Customers.
- A reason to be there: a support ticket, a billing dispute, a reproducibility check. Note the ticket ID before you start.
Procedure
Section titled “Procedure”-
Locate the customer
From the admin console, go to Customers and search by email or Public ID. Open the customer’s detail page.
Screenshot pending
Admin customer detail page with the Impersonate button in the header.
-
Start the impersonation
Click Impersonate in the customer header. The console calls
POST/api/customer/impersonation/startwith the customer’s user ID and, on success, redirects you to
/?as=<customerUserId>— the customer home, scoped to them.You’ll see the ImpersonationBanner pinned to the top of every page for the duration of the session. If the banner is missing, you are not impersonating — stop and check the URL for
?as=. -
Reproduce the issue
Navigate the customer surface as you normally would. Every request you make is scoped to the customer via the
?as=marker — chargers, sessions, receipts, EV cards all reflect what the customer sees.Keep the session short. Don’t initiate charging sessions, don’t change payment methods, don’t add or remove EV cards unless the ticket explicitly authorizes it.
-
End the impersonation
Click Exit on the ImpersonationBanner. The console calls POST
/api/customer/impersonation/end, logs the end event, and redirects you to/admin.The marker lives in the URL, so closing the tab or manually removing
?as=from the address bar also ends the impersonation on the next request. The Exit button is preferred because it produces a paired audit entry.
Verify
Section titled “Verify”- The ImpersonationBanner is gone and you’re back on
/admin. - Check Admin → Audit log and filter by your user ID. You should
see paired
impersonation.startandimpersonation.endentries with the customer’s user ID in the metadata, plus oneimpersonation_auditrow per privileged route you touched while impersonating. - Your admin session is intact — no re-login required. The start endpoint preserves your primary session and uses the URL marker for scoping, not a session swap.
If something goes wrong
Section titled “If something goes wrong”409 Already impersonating; end the current session first.
You have a stale ?as= marker in another tab or window. Find the
tab with the ImpersonationBanner and click Exit, or open
/api/customer/impersonation/end from devtools. Then retry.
403 Forbidden on start.
Your account isn’t role = admin. A privilege_violation entry is
written to the auth audit log for the attempt. If you should be an
admin, escalate to whoever manages role assignments — don’t retry.
The banner doesn’t appear after redirect.
The middleware didn’t pick up the ?as= marker. Confirm the URL
contains ?as=<id>. If it does and the banner is still missing, the
middleware step that sets ctx.state.actingAs isn’t firing — file an
incident; do not assume you’re impersonating.
Exit button does nothing.
The end endpoint treats audit-write failures as non-fatal and still
returns success, so the UI should always navigate. If the button is
truly inert, manually strip ?as= from the URL and reload — that
ends the impersonation on the server side via the middleware.
Audit and reversibility
Section titled “Audit and reversibility”Impersonation is read-mostly but not inherently reversible — if you take a destructive action while impersonating (deleting an EV card, cancelling a reservation), that action is real and affects the customer’s account. The audit trail tells you what happened, not how to undo it.
What gets logged:
- One
auth_auditrow with tagimpersonation.start, your user ID, and the target customer’s user ID in metadata. - One
impersonation_auditrow stamped at session start with the start route and method. - Additional
impersonation_auditrows per privileged route the middleware sees during the session (rate-limited). - One
auth_auditrow with tagimpersonation.endwhen you click Exit. If you close the tab instead, the end row may be missing — use Exit to guarantee the pair.
Reversing actions taken during impersonation: Find the actions in the customer’s normal activity history and undo them through standard admin tools (refund a charge, restore a reservation, re-issue an EV card). Reference the impersonation audit row IDs in your ticket notes so the chain is auditable end-to-end.