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 logged 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:
- Get an actor token that can be used to sign in as a different user.
- Detect an impersonated session as soon as you're signed in.
Actor tokens
Actor tokens are similar to sign-in tokens(opens in a new tab). They can be used for one-time logins, but they result in impersonated sessions. You can obtain an actor token from our Backend API(opens in a new tab).
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(opens in a new tab). 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(opens in a new tab) 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(opens in a new tab), 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 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 frontend (client-side) code, you can easily 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>} logged in as user {userId} </div> ); }
const { session } = window.Clerk; if (session.actor) { const { actor, user } = session; console.log(`User ${actor.sub} is signed in as user ${user.id}.`) }
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(opens in a new tab) 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.