Impersonation
Here you can read how impersonation functionality works step by step
Last updated
Here you can read how impersonation functionality works step by step
Last updated
Impersonation is the ability to log in as a specific user from the Teams List page. While impersonating, you can see the app exactly as that user does. In our app, this is particularly useful for logging in as a specific team owner.
However, you cannot log in as all owners; they can disable this option in their profile settings. We have the impersonationAllowed
field in the userEntity
that controls this:
On UI you can switch this option on Profile Setting page:
It is also other factors, with which you cannot impersonate user:
Your two-factor authentication is disabled
You are trying to impersonate yourself
You are trying to impersonate user with Super Admin role
You are trying to impersonate another Admin while you are not Super Admin
You are trying to impersonate other users when you are already impersonating someone
In api/src/auth/controller/two-factor-auth.controller.ts you can find impersonate endpoint:
As you can see, at first we should pass two-factor verification for security reasons. On the higher level we have JwtTwoFactorGuard which will check if user 2FA is enabled and AdminGuard which will check if user is Admin or Super Admin.
After that we move to the service which will handle security checks and if all passed, we will generate impersonation token:
In generateImpersonationAccessToken function we will create impersonation record, with randomly generated 24 characters code and user who done impersonation, timestamp will be generated automatically:
Next, we will generate JWT token with some extra fields:
As you can see we have 4 extra fields: impersonatedBy, impersonatedAt, impersonationCode, impersonatorTeamId. The impersonatorTeamId value is used to return impersonator to the team from where he ded impersonation. isTwoFactorEnable and isTwoFactorAuthenticated should be always setted to false, in case user has 2FA enabled, this logic will allow us to skip 2FA on this user. To regular field we pass user which will be impersonated credentials that will allow backend to identify impersonator like other user.
Token is valid for the next 30 minutes.
While impersonation we will have some functionality blocked.
On frontend currentUser
in context will have impersonatedBy
field by which we know when to disable specific actions and show impersonation alert.
Changing teams and creating new teams will be blocked both in the UI and on the backend. The reason for this is that changing teams requires generating new tokens, which would break the impersonation logic. To forbid that we can add simple condition:
Additionally, during impersonation, we will be able to leave comments on businesses and leads, but they will be posted under the impersonator's name, with the prefix 'Support team.' The same will apply to audit logs. This logic will allow us to clearly identify who performed the actions.
AuditLoggerEntity
, BusinessCommentEntity
and LeadCommentEntity
have isImpersonated field to identify which record was created while impersonation.
On backend we handle that scenario with one condition (similar for both logs and comments):
To return back, we will use the cancelImpersonation
function in the two-factor-auth.controller
. We will find the impersonation record by user, code, and timestamp to ensure we find the correct record (we normalize user.impersonatedAt
and truncate the timestamp to get accurate results, since JWT tokens don't support the timestamp format used in PostgreSQL). After that, we generate tokens for the admin, allowing them to return to their profile and team.
You can see full process of impersonation in block schemas: