Skip to main content

Implement user impersonation

Overview

Impersonating a user allows you to login as them without using their credentials. This is useful for testing purposes, or for customer support.

This guide shows you how to achieve this by only allowing a certain type of users, admins, to perform the impersonation.

Before you start

caution

Since this feature allows you to login as any user in your application, only admins or custom support staff should use it. You can use any method to protect this API. (API Key, specific user roles, IP address validation, etc.)

Steps

1. Create the impersonation endpoint

Create a new API endpoint that accepts some form of identifier (email, phone number, user ID, etc.) and creates a new impersonation session for that user.

In order for this to work, admins need to first log in to the application as themselves. Once they create their session (like any regular user's session), they can call the API via a frontend UI that's only shown to them. You can detect the admin role on the frontend by seeing this guide.

import express from "express";
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import Session from "supertokens-node/recipe/session";
import supertokens from "supertokens-node";
import UserRoles from "supertokens-node/recipe/userroles";

let app = express();

app.post(
"/impersonate",
verifySession({
overrideGlobalClaimValidators: async (globalValidators) => [
...globalValidators,
UserRoles.UserRoleClaim.validators.includes("admin")
],
}),
async (req, res) => {

let email = "..."; // read from request body

let user = await supertokens.listUsersByAccountInfo("public", {
email
});

if (user.length === 0) {
throw new Error("User does not exist");
}

await Session.createNewSession(req, res, "public", user[0].loginMethods[0].recipeUserId, {
isImpersonation: true,
});

res.json({ message: "Impersonation successful!" });
})
Multi Tenancy

Notice that the "public" tenantId goes to the function call above. This is the default tenantId in SuperTokens. If you are using the multi-tenancy feature and want to login into a different tenant, you can replace "public" with the tenantId you want to login into.

You can fetch this tenantId based on the admin user's tenant (from their session), or you can pass it in the request body.

  • The API should call from your frontend application such that the frontend SDKs' network interceptors are running.
  • In the API above, session verification runs first to ensure that the user has the admin role. If not, the API returns a 403 to the frontend.
  • The target user is then fetched based on their email ID. If the user does not exist, an error occurs (which you can map to a 400 status code).
  • A new session is then created using the target user's user ID. The isImpersonation flag goes as true in the access token payload to detect this on the frontend and show a message to the admin user that they are impersonating the target user (this is UI you would have to build if you want to). You can also use this custom access token payload to protect certain APIs which the admin cannot call, even if in impersonation mode. In the code, you use isImpersonation, but you can use anything else you like. In fact, you can even add the admin user's user ID to the access token payload (with a key like adminUserId), for logging purposes.
  • The new session tokens attach to the response and overwrite the existing admin session. Cookies apply if the request contains the st-auth-mode: "cookie" header, otherwise the mode is header-based auth. Since you would be calling this API via the frontend interceptors, you do not need to explicitly set this header since the frontend SDK does this on its own.
  • Once impersonated, the admin user can logout of the target user's session by clicking on the sign out button of your app - nothing special needs to happen there.