User Impersonation
User impersonation allows admins to view the database explorer as different user types to debug issues, test Row Level Security (RLS) policies, and provide customer support.
Overview
Section titled “Overview”The impersonation feature enables admins to see exactly what data users can query based on their RLS policies. This is invaluable for:
- 🐛 Debugging user-reported issues - See data exactly as the user sees it
- 🔒 Testing RLS policies - Verify security rules work correctly
- 🎯 Customer support - Understand what users are experiencing
- ⚙️ Testing different roles - Validate permissions for anon and service roles
Impersonation Modes
Section titled “Impersonation Modes”1. Specific User
Section titled “1. Specific User”Impersonate a real user by their ID to see data exactly as they would see it.
Use cases:
- Debugging user-reported data issues
- Verifying RLS policies for specific users
- Customer support investigations
How it works:
- Respects all RLS policies for that user
- Uses the user’s actual permissions
- All queries execute in their security context
2. Anonymous (anon key)
Section titled “2. Anonymous (anon key)”See data as an unauthenticated visitor would see it.
Use cases:
- Testing public data access
- Verifying anon-level RLS policies
- Ensuring sensitive data is protected from public access
How it works:
- Generates a temporary JWT with
role: "anon" - No user account required
- Only public data should be accessible
3. Service Role
Section titled “3. Service Role”View data with service-level permissions.
Use cases:
- Administrative queries
- Testing privileged operations
- Bypassing RLS for data management
How it works:
- Generates a JWT with
role: "service" - May bypass RLS (depending on configuration)
- Elevated permissions for admin tasks
Starting Impersonation
Section titled “Starting Impersonation”- Navigate to the Tables page in the admin dashboard
- Click the “Impersonate User” button in the header
- Select your impersonation type:
- Specific User - Search and select a user by email
- Anonymous - Impersonate as unauthenticated user
- Service Role - Use service-level permissions
- Enter a reason (required for audit trail)
- Example: “Support ticket #1234”
- Example: “Testing RLS policy for premium users”
- Click “Start Impersonation”
- The page reloads with impersonation active
- An orange warning banner appears showing who you’re impersonating
While Impersonating
Section titled “While Impersonating”When impersonation is active:
- ⚠️ Orange banner displays at the top of the screen
- All table queries use the impersonated user’s permissions
- Data grid shows only rows the impersonated user can access
- Edit/delete operations respect RLS policies
- You cannot start another impersonation (must stop first)
Stopping Impersonation
Section titled “Stopping Impersonation”- Click “Stop Impersonation” in the warning banner
- Session ends in the database
- Impersonation tokens are cleared
- Page reloads with admin context restored
How It Works
Section titled “How It Works”Two-Token Architecture
Section titled “Two-Token Architecture”The system maintains two separate JWT tokens:
// In localStoragefluxbase_admin_access_token; // Your admin tokenfluxbase_admin_user; // Your admin user infofluxbase_impersonation_token; // Target user's token (when active)fluxbase_impersonated_user; // Target user infofluxbase_impersonation_session; // Session metadataToken Selection
Section titled “Token Selection”All API requests automatically use the appropriate token:
const getActiveToken = () => { const impToken = localStorage.getItem("fluxbase_impersonation_token"); const adminToken = localStorage.getItem("fluxbase_admin_access_token"); return impToken || adminToken; // Impersonation takes precedence};RLS Integration
Section titled “RLS Integration”When querying data while impersonating:
- Frontend sends request with impersonation token
- API Client adds token to Authorization header
- Auth Middleware extracts user ID and role from JWT
- RLS Middleware sets PostgreSQL session variables:
SET LOCAL app.user_id = '<impersonated_user_id>'SET LOCAL app.role = '<impersonated_role>'
- Database enforces RLS policies based on these variables
- Results show only data the impersonated user can access
Security Features
Section titled “Security Features”Audit Trail
Section titled “Audit Trail”Every impersonation session is logged in the auth.impersonation_sessions table:
| Field | Description |
|---|---|
admin_user_id | Who performed the impersonation |
target_user_id | Which user was impersonated (nullable for anon/service) |
impersonation_type | Type: ‘user’, ‘anon’, or ‘service’ |
target_role | Role being impersonated |
reason | Why the impersonation occurred |
started_at | When it started |
ended_at | When it ended |
ip_address | IP address of the admin |
user_agent | Browser/client information |
is_active | Whether session is currently active |
Access Control
Section titled “Access Control”- ✅ Only users with
role = 'admin'can impersonate - ✅ Self-impersonation is prevented (for user mode)
- ✅ Reason field is required (cannot be empty)
- ✅ Only one active session per admin at a time
- ✅ Previous session auto-ends when starting new one
Visual Indicators
Section titled “Visual Indicators”- 🟠 Bright orange warning banner (cannot be dismissed)
- 📝 Shows impersonation type and target user
- 🔒 Impersonate button disabled while already impersonating
API Reference
Section titled “API Reference”Endpoints
Section titled “Endpoints”# Start impersonating a specific userPOST /api/v1/auth/impersonateContent-Type: application/jsonAuthorization: Bearer <admin_token>
{ "target_user_id": "uuid", "reason": "Support ticket #1234"}# Start impersonating anonymous userPOST /api/v1/auth/impersonate/anonContent-Type: application/jsonAuthorization: Bearer <admin_token>
{ "reason": "Testing public data access"}# Start impersonating with service rolePOST /api/v1/auth/impersonate/serviceContent-Type: application/jsonAuthorization: Bearer <admin_token>
{ "reason": "Administrative query"}# Stop impersonationDELETE /api/v1/auth/impersonateAuthorization: Bearer <admin_token># Get active impersonation sessionGET /api/v1/auth/impersonateAuthorization: Bearer <admin_token># List impersonation sessions (audit trail)GET /api/v1/auth/impersonate/sessions?limit=50&offset=0Authorization: Bearer <admin_token>Response Format
Section titled “Response Format”// Start impersonation response{ "session": { "id": "uuid", "admin_user_id": "uuid", "target_user_id": "uuid", "impersonation_type": "user", "target_role": "user", "reason": "Support ticket #1234", "started_at": "2024-01-15T10:30:00Z", "is_active": true, "ip_address": "192.168.1.1", "user_agent": "Mozilla/5.0..." }, "target_user": { "id": "uuid", "email": "user@example.com", "role": "user" }, "access_token": "eyJhbGc...", "refresh_token": "eyJhbGc...", "expires_in": 900}Troubleshooting
Section titled “Troubleshooting”Impersonation token not working
Section titled “Impersonation token not working”Symptoms: Queries return admin data instead of impersonated user’s data
Solutions:
- Check localStorage for
fluxbase_impersonation_token - Verify token is being sent in Authorization header
- Check backend logs for JWT validation errors
- Ensure you reloaded the page after starting impersonation
Data not filtered correctly
Section titled “Data not filtered correctly”Symptoms: Seeing more/less data than expected
Solutions:
- Verify RLS policies exist on the tables
- Check PostgreSQL session variables:
SHOW app.user_id - Ensure RLS middleware is enabled in backend config
- Verify the RLS policies use
app.user_idandapp.rolecorrectly
Cannot stop impersonation
Section titled “Cannot stop impersonation”Symptoms: Stop button doesn’t work or session persists
Solutions:
- Clear localStorage manually via browser DevTools
- Check for active session in
auth.impersonation_sessionstable - Verify DELETE endpoint is accessible (check CORS/network)
- Logout and login again to reset session
Users not appearing in search
Section titled “Users not appearing in search”Symptoms: User search returns no results
Solutions:
- Verify
exclude_adminsfilter isn’t hiding all users - Check user has non-admin role in database
- Ensure user exists and is not deleted
- Try searching with full email address
Best Practices
Section titled “Best Practices”1. Always Provide a Clear Reason
Section titled “1. Always Provide a Clear Reason”// ✅ Goodreason: "Support ticket #12345 - user reports missing data";
// ❌ Badreason: "testing";2. Stop Impersonation When Done
Section titled “2. Stop Impersonation When Done”Don’t leave impersonation sessions running. Always click “Stop Impersonation” when finished to:
- Clear audit trail properly
- Avoid confusion
- Prevent accidental data modifications
3. Review Audit Logs Regularly
Section titled “3. Review Audit Logs Regularly”Query the impersonation sessions table to monitor usage:
SELECT admin_user_id, target_user_id, impersonation_type, reason, started_at, ended_at, EXTRACT(EPOCH FROM (ended_at - started_at)) as duration_secondsFROM auth.impersonation_sessionsWHERE started_at > NOW() - INTERVAL '7 days'ORDER BY started_at DESC;4. Test RLS Policies with Multiple Scenarios
Section titled “4. Test RLS Policies with Multiple Scenarios”Use all three impersonation modes to thoroughly test:
- User mode: Test with regular users
- Anon mode: Verify public data access
- Service mode: Test admin operations
Related Documentation
Section titled “Related Documentation”- Authentication Guide - Learn about authentication and user roles
- API Cookbook - Examples of common API patterns
- Row-Level Security - Advanced RLS features and testing