How to build an admin mode to impersonate user accounts

4 min read Original article ↗

Parthi Loganathan

Why do I need an admin mode?

With almost any product you build that has signed-in users, you’ll quickly run into the need for some sort of admin or “God” mode that lets you access your user’s accounts. There are generally two motivations for this feature:

  1. Support A user gets stuck using your product and reached out for help. You might be able to understand the problem through Full Story, screen sharing or a screenshot/video from them and guide your user, but sometimes you just need to get into their account and verify everything is set up right or make some changes for the user on their behalf.
  2. Debugging A user ran into an issue and reported it. In addition to looking at your logs and database, you might want to actually check the state of the user’s account and see what they see.

Almost every company ends up building some variant of this. Some of them are more robust than others. For example, Clerky has a toggle that the user needs to flip for their support team to access your account.

Press enter or click to view image in full size

Staff Access in settings of Clerky

You’re probably wondering what’s the fastest way to implement this in a way that’s secure. I’ve had to build this over and over again and have never found a good resource online on the best way to do it. If you’re looking for something that’s quick and gets the job done, here’s an outline of how you can implement a basic admin mode.

How do I implement an admin mode?

In this example, we use Firebase, MongoDB, Node and Express, but the general principles should apply to whatever identity provider and server-side stack you use.

Step 1: Define admin spoofing in your user schema

Wherever you define your user, add two fields for admin controls:

  1. isAdmin determines whether this user is an admin and can access admin mode
  2. spoofUserId is the user ID of the user the admin is trying to impersonate

In our Mongo example, we define our fields as follows:

adminControls: {
isAdmin: {
type: Boolean,
default: false
},
spoofUserId: {
type: Schema.Types.ObjectId,
ref: "User"
}
}

as a part of our broader User schema which you can see below

Step 2: Swap the user if the above fields are set

In a typical server, when a request comes in from a logged-in user, we lookup a JWT token from our identity provider to match the user identity with the user in our database.

If the user is an admin as determined by the isAdmin field and has a spoofUserId set, we want to use the spoofUserId instead of the actual user. Basically letting our server know that we want this admin user to perform actions on behalf of the spoofed user. Let’s define a function getUserFromFirebaseId to make that swap for us.

Step 3: When a request comes in, decide whether to return a spoofed user

When a request comes in, we identify who made the request and then call the above function to check whether they’re an admin and trying to spoof another user. If so, we use the user ID of the spoofed user.

Now all data returned and actions performed are for the spoofed user that the admin is trying to impersonate.

If an admin wants to access a specific user’s account, they just need to make sure their isAdmin field is set to true and spoofUserId is set to the user you wish to impersonate. You can edit this in your database manually or make this available to non-technical support staff without database access by building an internal tool yourself or using something like Retool.

Off-the-shelf libraries

If you happen to be using Django, you can look into this nifty package, django-impersonate, which takes care of a lot of this for you. The closest thing I’ve found with Node is express-user-impersonation that uses Passport JS. Unfortunately, that was additional overhead I didn’t want to deal with when I already had everything working with Firebase.

There’s a lot more to consider…

Impersonating a user is something you want to be incredibly careful about. You should ask yourself a number of questions:

  1. Do I want my user’s permission before I access my account?
  2. How do I limit admin access to certain members of my company?
  3. How do I make sure an admin impersonating a user doesn’t accidentally treat it like their own account and mess up user data?
  4. How do I capture audit logs when an admin impersonates a user?

If you’re interested in implementing a secure admin mode without worrying about any of the above, check out helpelf.xyz, a low code admin mode that’s secure and compliant.

Press enter or click to view image in full size