EduShade
Auth Module

User Impersonation

Admin feature to log in as another user for support and debugging — supports two modes: read-only Impersonation and full-access Masquerade

User Impersonation

User impersonation lets administrators temporarily act as another user — essential for support, debugging, and reproducing user-specific issues without ever asking for credentials.

EduShade ships two distinct modes:

ModeWhat the admin can doToken view_mode
Impersonation (read-only)View the user's dashboard, courses, settings, etc. Write actions are blocked — POST/PUT/DELETE attempts return an error.impersonation
Masquerade (full access)Act as the user end-to-end: enroll, submit, change settings, post content. Every action is attributed to the user.masquerade

Choose Impersonation for safe diagnostic work, and Masquerade only when you need to perform an action as the user (e.g. completing a stuck workflow on their behalf).

Who Can Impersonate?

  • Users with the admin.users permission, or
  • Users with the is_admin flag set to true

Restrictions:

  • You cannot impersonate yourself.
  • You can only impersonate users in your same tenant.
  • Both modes are audited — every start/stop is published as an audit event.

How to Start Impersonation

  1. Go to Admin → Users → [select user] → Impersonation tab (/admin/users/{userID}/edit/impersonation)
  2. You will see two buttons:
    • Start Impersonation — read-only mode
    • Start Masquerade — full-access mode
  3. Click the mode you need. Confirm the action.
  4. You are redirected to the target user's dashboard.

What Happens Behind the Scenes

  1. Frontend calls POST /v1/auth/impersonate/{user_id} with { "view_mode": "impersonation" | "masquerade" }.
  2. Backend issues a new access token for the target user. The JWT contains an extra impersonated_by claim with the admin's user ID.
  3. Frontend snapshots your original admin token, refresh token, and user data to localStorage so they can be restored later.
  4. The view mode is stored in localStorage under es_impersonation_view_mode.
  5. An audit event impersonation_started is published with: admin ID, target user ID, view_mode, IP, user agent.

While Impersonating

  • An ImpersonationBanner is shown at the top of every page so you cannot forget you are impersonating.
  • The banner shows: target user name, view mode, and a Stop button.
  • In Impersonation mode (read-only): write operations are rejected by the backend; the UI may still render forms but submissions will fail.
  • In Masquerade mode: the target user's roles, permissions, and identity apply to every request. Any data you create or modify is attributed to them.

What to Be Careful About

  • In Masquerade, profile changes, enrollments, purchases, and submissions are all stored against the user — there is no automatic rollback.
  • Avoid Masquerade unless you specifically need to write on the user's behalf.
  • For pure investigation, always prefer Impersonation.

How to Stop Impersonation

  1. Click Stop in the impersonation banner (or the Return to Admin option in the user menu).
  2. Frontend calls POST /v1/auth/impersonate/stop.
  3. Your original admin token, refresh token, and user data are restored from localStorage.
  4. Impersonation localStorage keys are cleared.
  5. You are redirected to the page you started from (or the admin dashboard).
  6. An audit event impersonation_stopped is published.

Browser Storage During Impersonation

The frontend uses the following localStorage keys to preserve admin state and track the impersonated session. (Source of truth: src/lib/auth/impersonation/session.ts.)

KeyPurpose
es_impersonation_activeBoolean flag — "true" while an impersonation session is active
es_impersonation_view_modeCurrent mode — "impersonation" or "masquerade"
es_original_admin_tokenThe admin's original access token (restored on stop)
es_original_admin_refresh_tokenThe admin's original refresh token
es_original_admin_user_dataThe admin's user profile snapshot
es_impersonated_user_idThe target user's ID (decoded from the impersonation JWT)
es_impersonated_byAdmin user ID (mirror of the JWT impersonated_by claim)
es_impersonated_user_dataSnapshot of the target user's profile
es_impersonation_start_pageURL to return to after stopping
es_restored_admin_user_dataAdmin profile data restored after stopping (transient)

The active access/refresh tokens during impersonation continue to live under the regular es_auth_access_token / es_auth_refresh_token keys — that's how the rest of the app sees the impersonated session as the "current" session.

Audit Trail

Every impersonation transition is logged for security and compliance:

EventData Logged
impersonation_startedAdmin ID, Target User ID, view_mode, Timestamp, IP, User Agent
impersonation_stoppedAdmin ID, Target User ID, view_mode, Timestamp, IP, User Agent

These are published to the platform's pub/sub event stream and can be viewed by administrators with audit.view permission.

JWT Claim: impersonated_by

While impersonating (either mode), the JWT issued to the admin contains:

  • user_id → the target user's ID (so the rest of the system treats requests as the user)
  • impersonated_by → the admin's user ID
  • view_mode"impersonation" or "masquerade"

Backend services use the impersonated_by claim to:

  • Allow read-only operations in Impersonation mode and reject writes
  • Tag downstream audit/activity events so any side-effects are traceable to the originating admin

Security Considerations

  • The original admin session is preserved only in browser storage (not on the server). If localStorage is cleared mid-session, the admin must log back in manually.
  • An impersonation token is just a regular access token with extra claims — same expiry, same revocation rules. Logging out the impersonated session also ends the impersonation.
  • Always prefer Impersonation (read-only) for diagnostic work to avoid accidental writes on the user's behalf.

Troubleshooting

IssueSolution
"You don't have permission to impersonate"You need the admin.users permission or the is_admin flag
"Cannot impersonate yourself"Self-impersonation is not allowed
"User not found"The target user may be soft-deleted, suspended, or in a different tenant
Write actions fail unexpectedlyYou are in Impersonation (read-only) mode — restart in Masquerade mode if writes are required
Can't stop impersonationClear all es_impersonation_* and es_original_admin_* keys from localStorage and log in again
Lost admin session after impersonationBrowser storage was cleared. Log back in with your admin credentials
Actions attributed to the wrong userIn Masquerade, actions are always attributed to the impersonated user — this is by design

On this page