User Impersonation | PropelAuth BYO Documentation
User Impersonation
When customers report bugs you can’t reproduce, impersonation lets your support and engineering teams see exactly what users see.
PropelAuth BYO Impersonation provides secure, time-limited access to act as any user. It tracks who impersonated whom, lets you instantly revoke access, and distinguishes impersonation sessions from regular sessions so you can add your own logging or restrictions.
How Impersonation Works
Impersonation involves two parties: an employee (someone on your team) and a user (your customer).
- Employee initiates - A support agent or engineer starts an impersonation session from your admin dashboard
- System creates token - PropelAuth BYO generates a special impersonation token tied to both the employee and user
- Employee uses token - The token lets the employee access your app as the user
- Session is distinguishable - Your app knows this is an impersonation session, not a regular login
- Session expires - After a set time (default: 1 hour), the session automatically ends
The beauty is that your application code barely changes. You validate impersonation tokens almost exactly like regular session tokens, just with a different function call.
Basic Usage
Let’s walk through implementing impersonation in your application.
Creating an Impersonation Session
To begin, you’ll need to set up a route that your employees can call to create an impersonation session:
Node
app.post("/api/admin/impersonate", async (req, res) => {
// Get the employee from your auth system (e.g., from their session)
const employeeEmail = getEmployeeEmail(req);
const { userId } = req.body;
// Create the impersonation session
const result = await auth.impersonation.create({
employeeEmail: employeeEmail,
targetUserId: userId,
userAgent: req.headers["user-agent"],
ipAddress: req.ip,
});
if (!result.ok) {
if (result.error.type === "UnauthorizedEmployee") {
return res.status(403).json({ error: "Not authorized to impersonate" });
}
console.error("Failed to create impersonation session:", result.error);
return res.status(500).json({ error: "Failed to create impersonation session" });
}
// We recommend using the same cookie that your regular sessions use to avoid ambiguity
res.cookie("sessionToken", result.data.impersonationSessionToken, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 1000, // 1 hour
});
res.json({ success: true });
});
Python
class ImpersonateRequest(BaseModel):
user_id: str
@app.post("/api/admin/impersonate")
async def impersonate(impersonate_request: ImpersonateRequest, request: Request, response: Response):
# Get the employee from your auth system (e.g., from their session)
employee_email = get_employee_email(request)
# Create the impersonation session
result = await client.impersonation.create(
employee_email=employee_email,
target_user_id=impersonate_request.user_id,
user_agent=request.headers.get("user-agent"),
ip_address=request.client.host
)
if not is_err(result):
if result.error.type == "UnauthorizedEmployee":
raise HTTPException(status_code=403, detail="Not authorized to impersonate")
print("Failed to create impersonation session:", result.error)
raise HTTPException(status_code=500, detail="Failed to create impersonation session")
# We recommend using the same cookie that your regular sessions use to avoid ambiguity
response.set_cookie(
key="sessionToken",
value=result.data.impersonation_session_token,
httponly=True,
secure=True,
samesite="lax",
max_age=60 * 60 # 1 hour
)
return {"success": True}
Validating Sessions (Regular or Impersonation)
Use the same cookie for both regular and impersonation sessions, checking the prefix to determine which validation to use:
Node
// GET /api/user/profile
app.get("/api/user/profile", async (req, res) => {
const sessionToken = req.cookies.sessionToken;
if (!sessionToken) {
return res.status(401).json({ error: "Not authenticated" });
}
// Check if this is an impersonation session
if (sessionToken.startsWith("impersonate_")) {
return validateImpersonationSession(sessionToken);
} else {
return validateRegularSession(sessionToken);
}
});
Ending Sessions
Your logout endpoint should handle invalidating both regular and impersonation sessions:
// POST /api/logout
app.post("/api/logout", async (req, res) => {
const sessionToken = req.cookies.sessionToken;
if (!sessionToken) {
return res.status(200).json({ success: true });
}
if (sessionToken.startsWith("impersonate_")) {
// Handle impersonation sessions
await auth.impersonation.invalidateByToken({
impersonationSessionToken: sessionToken,
});
} else {
// This is your existing logout logic
await logoutOurSession(sessionToken);
}
// Clear the session cookie
res.clearCookie("sessionToken");
res.json({ success: true });
});
Configuring Who Can Impersonate
Not everyone should be able to impersonate users. PropelAuth BYO gives you three ways to control access through your user_impersonation.jsonc configuration file:
{
"absolute_lifetime_secs": 3600, // 1 hour
"who_can_impersonate": {
"allowed_employee_emails": ["support@company.com", "john@company.com"],
}
}
Security Considerations
Impersonation Audit Trail
PropelAuth BYO maintains a complete audit trail of impersonation sessions:
- Who impersonated whom
- When sessions started and ended
- Failed impersonation attempts
- Manual session invalidations
Instant Revocation
Immediately revoke access when needed using either the Invalidate All For Employee or Invalidate All for User functions:
// Revoke all sessions for a compromised employee account
await auth.impersonation.invalidateAllForEmployee({
employeeEmail: "compromised@company.com",
});
// Stop all impersonation of a specific user
await auth.impersonation.invalidateAllForUser({
userId: sensitiveUserId,
});
Restricting Actions During Impersonation
Since you can detect when someone is impersonating, you can prevent sensitive actions:
// Any sessions validated with client.impersonation.validate() should add a flag like this
if (user.isImpersonation) {
// Block sensitive operations like payment changes
return res.status(403).json({
error: "Cannot modify payment methods during impersonation",
});
}
Working with Sessions
Impersonation tokens work seamlessly with PropelAuth BYO’s session management. You can use the same patterns and features:
// Impersonation benefits from session features
const result = await client.impersonation.create({
employeeEmail: employeeEmail,
targetUserId: userId,
userAgent: req.headers["user-agent"],
ipAddress: req.ip,
metadata: {
ticketId: "SUPPORT-1234",
reason: "Customer requested help with billing",
},
});
Dashboard Management
The PropelAuth BYO dashboard gives you visibility into all impersonation activity: Active Sessions - View current impersonation sessions with who is impersonating whom, start time, and quick invalidation.
Audit Trail - Complete history of who impersonated whom, when sessions started/ended, and any manual invalidations.
Emergency Controls - Invalidate all sessions for an employee, block specific employees, or stop all impersonation of a user.