Deployments and Testing

User Impersonation

User impersonation is a Descope feature that enables privileged users to act on behalf of another user.

It is particularly useful for:

  • Troubleshooting: Reproduce user issues directly.
  • Testing: Validate user-specific functionality without sharing credentials.
  • User Support: Provide direct assistance in the user's context.

This guide explains how impersonation works, how to configure permissions, how to create and embed flows for consent, impersonation, stopping impersonation, step-up authentication, and how to understand and verify impersonation JWTs.

Permissions and Access Control

Note

For more information on roles and permissions within Descope, you can review the Authorization docs.

Only users with the Impersonate permission can impersonate other users.

This permission can be assigned in two ways:

LevelDescription
Project-levelAllows impersonating any user in the project.
Tenant-levelRestricts impersonation to users within a specific tenant.

To grant impersonation rights:

  1. In the Authorization > RBAC page, create or edit a role. This can also be done programatically via SDKs or APIs as well.
  2. Add the Impersonate permission to the role.
  3. In the Users tab, assign the role to a user.

Best Practice

Only trusted administrators or support staff should have impersonation access.

Tenant Level Impersonation

In Descope, impersonation privileges can be scoped to a tenant. This is useful when you want to restrict impersonation to users within a specific tenant.

If a user has a tenant-level role with the Impersonate permission, they will only be able to impersonate users within that tenant.

  1. In the Authorization > RBAC page, create or edit a role (e.g., Tenant Admin). This can also be done programatically via SDKs or APIs as well.
  2. Assign the Impersonate permission to that role.
  3. In the Users tab, assign the role to the user for a specific tenant.

This restricts impersonation to users within that tenant. User consent is scoped separately. By default, consent a user grants in one tenant also applies in every other tenant they belong to, unless you limit it to a single tenant as described in Tenant-Scoped Consent.

Tenant-level impersonation example

Impersonation Flow Actions

Descope provides three Flow actions related to impersonation:

Flow ActionDescriptionConfiguration Options
User / ImpersonateStarts impersonation of another user.Optionally validate user consent before impersonation. Optionally add a step-up claim to the issued JWT.
Update User / Impersonation ConsentCollects user consent for impersonation.Set consent expiration (in hours). Optionally limit consent to the user's selected tenant.
User / Stop ImpersonationEnds impersonation and returns to the original user's session.No additional configuration available.

If you wish to allow/enforce user granting consent before impersonation, you can do so by adding the Update User / Impersonation Consent action to the flow, described in the Gathering User Consent section. Alternatively, consent can be granted programmatically via the Update User Impersonation Consent API.

To allow the impersonating user to complete a step-up action within the impersonated session, see Step-Up Authentication During Impersonation.

Otherwise, skip to the Impersonating a User with Descope Flows section, to learn more about how to impersonate a user.

Before impersonation, users can grant consent to be impersonated in two ways:

  1. User Impersonation Consent Flow - User-facing flow where users explicitly grant consent (recommended for interactive scenarios)
  2. Management API - Programmatically grant consent for automated setups and administrative workflows (see Grant Consent with the Management API).

In a multi-tenant project, a user can belong to several tenants. By default, consent is not tied to any of them, so consent the user grants in one tenant also allows impersonation in every other tenant they belong to.

Unscoped consent applies across all tenants

If a user belongs to more than one tenant and grants consent without a tenant, an admin with tenant-level impersonation in any of those tenants can impersonate them. If you want consent to stay within the tenant where it was given, you should scope it to that tenant.

You can scope consent to a single tenant from either the consent flow or the Management API. Once a consent is scoped, impersonation is only allowed into that tenant:

  • If the impersonation request selects a different tenant, it fails because the user has not given consent for that tenant.
  • If the impersonation request does not select a tenant, the impersonator is placed in the consented tenant.
  • If the user has since been removed from the consented tenant, impersonation is refused.

The tenant scope is only checked when impersonation runs with consent validation enabled. If you skip consent validation, the scope is not applied.

In order to be able to grant consent to be impersonated, the user must be authenticated first.

If the user is already authenticated, the user will still have to login again to grant consent. This effectively acts as a step-up or MFA action, in this case.

An example of requiring the user to authenticate again before allowing consent

To allow the user to grant consent, add the Update User / Impersonation consent action to the flow by clicking the + in the top left of the Descope flow editor.

Once added, connect within the flow accordingly, and edit the action to configure the Consent Expiration In Hours.

To scope the consent to one tenant, you can also check Limit consent to the user's selected tenant on the action. The consent is then recorded for the tenant the user selected in the flow, or the tenant passed in the flow's start options. If the flow has no selected tenant, the consent is recorded without a tenant and applies to all of the user's tenants.

Leaving the option unchecked records an unscoped consent. This also clears any tenant scope from a consent the user granted earlier.

An example of adding the Update User / Impersonation consent action within Descope flows

Once the user consent has been granted, you will be able to view the consent expiration within the User's page of the Descope console.

An example of the consent expiration within the users page in the Descope Console

You can grant consent directly with the Update User Impersonation Consent API, without the user completing a consent flow.

Note

This endpoint requires a management key, which can be generated here.

curl -X POST "__BaseURL__/v1/mgmt/user/update/impersonationConsent" \
  -H "Authorization: Bearer <Project ID>:<Management Key>" \
  -H "Content-Type: application/json" \
  -d '{
    "loginId": "user@company.com",
    "impersonationConsent": 1700000000,
    "tenantId": "T2abc123"
  }'
  • loginId (string, required) - The login ID of the user granting consent.
  • impersonationConsent (int32, required) - The Unix timestamp, in seconds, at which the consent expires.
  • tenantId (string, optional) - The ID of the tenant to scope the consent to. The user must belong to this tenant.

If you leave out tenantId, any tenant scope already on the user's consent stays as it is. This way, renewing a consent from an older integration does not widen it to all tenants. To remove an existing scope, you can send tenantId as an empty string.

Note

The impersonationConsent value is an absolute point in time, not a duration.

Consent is considered granted only while that timestamp is in the future, which is checked whenever impersonation runs with consent validation enabled. Sending a timestamp in the past, or 0, revokes any consent the user previously granted.

The response contains the updated user object.

Impersonating a User with Descope Flows

This section covers how to create a flow that allows you to impersonate a user. If you wish to manage impersonation via SDKs or APIs, you can see our User Impersonation with SDKs guide instead.

Create the User Impersonation Flow

In your impersonation flow, you'll need to create a screen with the Impersonated User input field within it. This field will take a login ID of the user you wish to impersonate.

An example of a user impersonation screen within a Descope flow

Afterwards, you'll need to add the User / Impersonate action in the flow after the screen.

If you wish to bypass user consent to be impersonated, you can uncheck the Validate user consent option on this action. However, this is not recommended when running in a production environment for security reasons.

If you wish to perform actions that require a step-up claim, you can check the Add stepup claim to JWT option. More details on this can be found in the Step-Up Authentication During Impersonation section.

An example of a impersonate user Descope flow

Finally if you wish to allow the impersonating user to stop impersonation, you can add a path in your flow with the User / Stop Impersonation action to accomplish this.

Using the Impersonation Flow

In order to begin impersonating a user through a flow, a user who possesses the Impersonate permission must be authenticated first. See the Permissions and Access Control section above for more details on setting up the required permissions.

After the impersonator has successfully authenticated and impersonated a user, Descope will return a user token with the sub claim set to the impersonated user's ID. If you typically include additional claims in your user token, you'll need to add a Custom Claims Action to the flow to set these claims. This is described in further detail below.

You can also validate that the user was successfully impersonated by searching the Audit Trail for the string Impersonate.

Note

If you wish to validate the impersonated session JWT, you can do so by sending the DS token to the Validate Session API endpoint.

Stop Impersonation in Flow

The Stop Impersonation action enables users to seamlessly switch back to their original account during an impersonation session, eliminating the need for manual logout and re-authentication.

This action can be triggered after a Load User action in the flow, utilizing the existing impersonated session.

Stop Impersonate Action in Descope flow

After adding this action, once you successfully end the flow, a JWT for the user will be returned without the impersonator's user ID within act[sub].

{
  "drn": "DS",
  "exp": 1693325322,
  "iat": 1693324722,
  "iss": "P2UcQcyxrjSA3mr6y0xZKRYI5oJz",
  "rexp": "2023-09-26T15:58:42Z",
  "sub": "U2UcRpsA4DSJ8kBvp6jikPyJ3aJ8"
}

Step-Up Authentication During Impersonation

The User / Impersonate action includes an Add stepup claim to JWT option. When enabled, the issued impersonation token will include the su: true claim, signaling to your application that this session has step-up authorization. This is useful when you want to gate sensitive operations — such as accessing billing details or making account changes — on a stepped-up impersonation session.

To enable it, open the User / Impersonate action in your flow and check Add stepup claim to JWT.

The User / Impersonate action panel showing the Add stepup claim to JWT checkbox

When this option is enabled, the resulting impersonation JWT will include su: true alongside the standard act.sub claim:

{
  "act": {
    "sub": "U2UcRpsA4DSJ8kBvp6jikPyJ3aJ8"
  },
  "sub": "U2UcRIInQ56lEhuRtxWx1NsmgxaS",
  "su": true,
  "iss": "P2UcQcyxrjSA3mr6y0xZKRYI5oJz",
  "iat": 1693324722,
  "exp": 1693325322,
  "rexp": "2023-09-26T15:58:42Z",
  "drn": "DS"
}

Understanding Impersonation JWTs

When impersonation succeeds, the session JWT reflects both the impersonator and impersonated user.

The impersonator's User ID is stored within the act.sub claim.

Token exchange also uses act, but there act.sub holds the client ID of the app that made the exchange. When a service exchanges an impersonated session token, the impersonation act stays in the new token, nested inside the exchange's act.

{
  "act": {
    "sub": "U2UcRpsA4DSJ8kBvp6jikPyJ3aJ8"
  },
  "sub": "U2UcRIInQ56lEhuRtxWx1NsmgxaS",
  "iss": "P2UcQcyxrjSA3mr6y0xZKRYI5oJz",
  "iat": 1693324722,
  "exp": 1693325322,
  "rexp": "2023-09-26T15:58:42Z",
  "drn": "DS"
}

Displaying Impersonator Information

Note

In order to refresh the values of custom claims in the token, such as if a custom attribute value for the user is changed, you'll need to make a request to the me endpoint, using either our SDKs or API.

When using impersonation, you may want to display information about the impersonator in your application's frontend. To access information about the impersonator, you need to read the session JWT.

In a flow, you can add information to the token by using the Custom Claims Action. Note that when user attribute custom claims (e.g. user.name) are set before the impersonation action in the flow, they reflect the impersonator. When custom claims are set after the impersonation action, they reflect the impersonated user.

It's worth noting that if you're managing your session token with cookies, the frontend will not be able to read the JWT claims to retrieve impersonator info. Therefore you'll have to manage returning this information manually from your backend, as described in the following steps:

  • From the frontend, send a request including the JWT to your backend.
  • In the backend, validate the JWT using one of the Backend SDKs or the API.
  • Extract the impersonator's user ID from the act.sub claim in the validated JWT.
  • Use the Management SDK or API to fetch the impersonator's details using the extracted user ID.
  • Return the impersonator's details to the frontend for display.

Auditing

All impersonation actions are logged in the Audit Trail as LoginSucceed with method Impersonate, showing both impersonator and impersonated user IDs.

Was this helpful?

On this page