User Impersonation
Impersonation allows admins or support to sign in as other users for debugging, customer support, or demonstrations.
Configuration
Section titled “Configuration”Enable impersonation in your createAuth configuration:
export const auth = createAuth({ adapter, providers, roles: { adminRoles: ['admin'], adminUserIds: ['special-admin-id'], }, impersonation: { enabled: true, allowedRoles: ['admin', 'support'], cannotImpersonate: ['admin'], maxTTL: 3600, onImpersonate: ({ adminUserId, targetUserId, reason, timestamp }) => { console.log(`Audit: ${adminUserId} impersonated ${targetUserId}: ${reason}`) }, },})Options
Section titled “Options”enabled- Set totrueto enable the impersonation featureallowedRoles- Array of roles that can impersonate others (defaults toadminRoles)cannotImpersonate- Array of roles that cannot be impersonated (defaults toadminRoles)maxTTL- Maximum duration of an impersonation session in seconds (default: 3600)onImpersonate- Hook called when impersonation starts
Starting Impersonation
Section titled “Starting Impersonation”Use the startImpersonation method to begin impersonating a user.
reason is optional, it’s passed to the onImpersonate hook for auditing purposes, you can also override the default ttl here.
import { auth } from '$lib/server/auth'
export async function POST({ request, locals }) { const session = await locals.getSession()
if (!session?.user?.isAdmin) return new Response('Forbidden', { status: 403 })
const { targetUserId, reason } = await request.json()
const result = await auth.startImpersonation(session.user.id, targetUserId, { reason, ttl: 60 * 30, })
if (!result) return new Response('Impersonation failed', { status: 500 })
return new Response(JSON.stringify({ success: true }), { headers: [ ['Set-Cookie', result.cookie], ['Set-Cookie', result.originalCookie], ], })}Result
Section titled “Result”token- The impersonation session JWT containingimpersonatedByandimpersonationExpiresAtclaimscookie- Set-Cookie header for the impersonation sessionoriginalCookie- Set-Cookie header to stash the admin’s session infomaxAge- The actual TTL used (capped by maxTTL)
Detecting Impersonation
Section titled “Detecting Impersonation”Check if the current session is an impersonation session:
import { isImpersonating } from '@rttnd/gau'
export async function load({ locals }) { const session = await locals.getSession()
return { user: session?.user, isImpersonating: isImpersonating(session?.session), impersonatedBy: session?.session?.impersonatedBy, }}Use this to show a visual indicator in your UI that the user is in impersonation mode.
Ending Impersonation
Section titled “Ending Impersonation”Restore the admin’s original session when they’re done:
import { auth } from '$lib/server/auth'
export async function POST({ request }) { const result = await auth.endImpersonation(request)
if (!result) return new Response('No active impersonation', { status: 400 })
const headers = new Headers() headers.set('Set-Cookie', result.cookie) result.clearCookies.forEach(cookie => headers.append('Set-Cookie', cookie))
return new Response(JSON.stringify({ success: true }), { headers })}Result
Section titled “Result”token- The restored admin session JWTcookie- Set-Cookie header for the restored sessionclearCookies- Array of Set-Cookie headers to clear the stash cookie
Best Practices
Section titled “Best Practices”- Log all impersonation events via the
onImpersonatehook - Set a reasonable
maxTTL - Display a clear visual indicator when impersonation is active