Docs

User Impersonation

User Impersonation allows you to sign in as a different user in your application. It allows administrators to access and operate on an instance as if they were signed in as a different user of that instance.

User Impersonation allows one user (Alice) to interact with your application as another (Bob). For the duration of an impersonated session, the application considers Alice to be Bob. Alice is given all the rights that Bob has, and is indistinguishable from Bob in that context.

User Impersonation can be useful for testing or debugging purposes. It is a powerful feature during troubleshooting or investigation processes carried out by customer support teams.

However, please consider when and how you use User Impersonation. It is advised to seek the impersonated user's consent and respect your users' privacy.

How User Impersonation works

Clerk allows developers or admins of an application to sign in as different users. The feature involves two parts:

  1. Get an actor token that can be used to sign in as a different user.
  2. Detect an impersonated session as soon as you're signed in.

Actor tokens

Actor tokens are similar to sign-in tokens. They can be used for one-time sign-ins, but they result in impersonated sessions. You can obtain an actor token from our Backend API.

Actor tokens need to declare the impersonator user (actor) and the impersonated user (subject). When Alice decides to impersonate Bob, they will issue an actor token. Alice is the actor and Bob is the subject of the Impersonation.

You can also configure the validity duration of an actor token by setting an expiration time, but you can revoke it at any time.

Create an actor token from the Backend API

curl -X POST https://api.clerk.com/v1/actor_tokens -d '{ \
  "user_id": "user_1o4qfak5AdI2qlXSXENGL05iei6", \
  "expires_in_seconds": 600 \
  "actor": { \
    "sub": "user_21Ufcy98STcA11s3QckIwtwHIES", \
  } \
}'

The above request will create an actor token that is valid for 600 seconds (10 minutes). Using the generated token will result in user with ID user_21Ufcy98STcA11s3QckIwtwHIES (the actor) signing in as user with ID user_1o4qfak5AdI2qlXSXENGL05iei6 (the subject).

When creating actor tokens, the object that you pass as the actor parameter will end up in the authentication token's act claim. You can read more details in the JWT claims section of this document.

Revoke an actor token from the Backend API

curl -X POST https://api.clerk.com/v1/actor_tokens/act_2EL6mQKzeUtoRwGuLZsznyfkIsH/revoke

The above request will revoke the actor token with ID act_2EL6mQKzeUtoRwGuLZsznyfkIsH even if it's not expired yet. Revoked actor tokens can no longer be used for signing in.

Sign in with an actor token

Actor tokens are consumed the same way as sign in tokens.

Actor tokens can be created from the Backend API. Once you've successfully created an actor token, you can use the url attribute of the response to consume the token and impersonate a user.

The url attribute is a Clerk Frontend API URL that will use the token to sign out existing users and prepare the sign-in object for impersonation. You can directly visit the url provided in the response to consume the actor token.

The Clerk Frontend API will redirect you to the /sign-in page of your application, where you can continue the flow by consuming the __clerk_ticket parameter.

If you're using ClerkJS directly and implementing a custom sign in flow, you should provide the token when creating a sign-in attempt.

How to detect impersonated sessions

Once a user is signed in as a different user, Clerk provides APIs and helper methods to distinguish an impersonated session from a regular session. It also provides the whole actor object, which contains information about the impersonator user.

JWT claims

Following the standard actor claim of RFC 8693, the Clerk session token includes an act claim. The act.iss claim is the referrer of the token. The act.sid claim is the session ID of the impersonated session. The act.sub claim is the ID of the impersonator.

{
  "act": {
    "iss": "https://dashboard.clerk.com",
    "sid": "sess_456",
    "sub": "user_456"
  },
  "azp": "https://your-site.accounts.dev",
  "exp": 1697726976,
  "iat": 1697726916,
  "iss": "https://your-site.clerk.accounts.dev",
  "nbf": 1697726906,
  "org_id": "org_123",
  "org_role": "org:member",
  "org_slug": "slug",
  "sid": "sess_123",
  "sub": "user_123"
}

The above JSON snippet shows what a Clerk session token looks like when a user is signed in as another user. The sub claim is the impersonated user (user_123), while act.sub contains the ID of the impersonator (user_456). The iss claim is the Clerk Dashboard because the user was impersonated from the Clerk Dashboard. The sid claim is the session ID of the impersonated user (sess_123), while act.sid contains the session ID of the impersonator's session (sess_456).

Note

Note that when using a custom JWT template, the {{session.actor}} will need to be added as a claim in order to expose it.

Detect impersonated sessions in the frontend

When working with client-side code, you can detect impersonated sessions and gain access to the actor ID or other information from the act claim.

import { useAuth } from "@clerk/nextjs";
import { withServerSideAuth } from "@clerk/nextjs";

// SSR authentication context
export const getServerSideProps = withServerSideAuth(
  async ({ req }) => {
    // The request is augmented with an auth object.
    // The actor object is available in there.
    const { userId, actor } = req.auth;

    return {
      props: { userId, actor },
    };
  }
);

function Home({ userId, actor }) {
  return (
    <div>
      Server side info:
      <p>
        {actor && <span>User {actor.sub} has </span>}
        signed in as user {userId}
      </p>

      <ClientSideInfo />
    </div>
  )
}

function ClientSideInfo() {
  // Client-side authentication context.
  const { userId, actor } = useAuth();

  return (
    <div>
      Client side info:
      <p>
        {actor && <span>User {actor.sub} has </span>}
        signed in as user {userId}
      </p>
    </div>
  );
}
import { useAuth } from "@clerk/react";

function Home() {
  const { userId, actor } = useAuth();

  return (
    <div>
      {actor && <span>user {actor.sub} has </span>}
      signed in as user {userId}
    </div>
  );
}
main.js
import { Clerk } from '@clerk/clerk-js';

// Initialize Clerk with your Clerk publishable key
const clerk = new Clerk("YOUR_PUBLISHABLE_KEY");
await clerk.load();

const { session } = clerk;

if (session.actor) {
  const { actor, user } = session;

  console.log(`User ${actor.sub} is signed in as user ${user.id}.`)
}
index.html
<script
  async
  crossorigin="anonymous"
  data-clerk-publishable-key="YOUR_PUBLISHABLE_KEY"
  src="https://[your-domain].clerk.accounts.dev/npm/@clerk/clerk-js@latest/dist/clerk.browser.js"
  type="text/javascript"
></script>

<script>
window.addEventListener("load", async function () {
  await Clerk.load();

  const { session } = Clerk;

  if (session.actor) {
    const { actor, user } = session;

    console.log(`User ${actor.sub} is signed in as user ${user.id}.`)
  }
});
</script>

Detect impersonated sessions in the backend

When working with backend code, Clerk provides middleware that can be used in Next.js API routes or directly in express-like Node.js applications. The middleware will provide information about impersonated sessions and the actor ID.

// pages/api/some-handler.js
import { withAuth } from "@clerk/nextjs";

export default withAuth(async (req) => {
  // The request object is augmented with the
  // Clerk authentication context.
  const { userId, actor } = req.auth;

  // The response includes actor and user IDs.
  return { data: { userId, actor } };
});
import express from "express";
import { ClerkExpressWithAuth } from "@clerk/clerk-sdk-node";

const app = express();

// Apply the Clerk express middleware
app.get(
  "/protected-endpoint",
  ClerkExpressWithAuth({
    // ...options
  }),
  (req, res) => {
    // The request object is augmented with the
    // Clerk authentication context.
    const { userId, actor } = req.auth;

    res.json({ userId, actor });
  }
);

app.listen(3000, () => {
  console.log("Booted.")
});

Impersonate a user from the Clerk Dashboard

If you prefer, you can impersonate a user right from the Users page in the Clerk Dashboard.

To impersonate a user, click on the menu icon (three stacked dots) on the right side of a user's row. A dropdown menu will appear. When you click on the Impersonate user option, your application instance should open in a new tab with the impersonated user signed in.

Feedback

What did you think of this content?