switchback / laravel-impersonation
Session-based user impersonation with explicit authorization and customizable Blade and Vue banners.
Package info
github.com/nashsaint/laravel-impersonation
pkg:composer/switchback/laravel-impersonation
Requires
- php: ^8.2
- illuminate/auth: ^12.0 || ^13.0
- illuminate/contracts: ^12.0 || ^13.0
- illuminate/http: ^12.0 || ^13.0
- illuminate/routing: ^12.0 || ^13.0
- illuminate/session: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- illuminate/view: ^12.0 || ^13.0
Requires (Dev)
- laravel/pint: ^1.27
- orchestra/testbench: ^10.0 || ^11.0
- phpunit/phpunit: ^11.5 || ^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A reusable, session-based impersonation package for Laravel 12 and 13. Explicit authorization, a visible return banner, and optional lifecycle events. No telemetry or application-specific user schema.
Installation
After publishing this package to a Composer repository:
composer require switchback/laravel-impersonation php artisan vendor:publish --tag=impersonation-config
Laravel discovers the service provider automatically. Define the configured impersonate gate in your application. Without this gate, impersonation is denied. For example:
Gate::define('impersonate', fn (User $actor, User $target): bool => $actor->is_admin && ! $target->is_admin );
Adapt this policy to your own roles, tenant boundaries, and target restrictions. The package independently rejects self-impersonation and nested impersonation. Both users must belong to the configured session guard's provider; integer and string identifiers are supported.
Set impersonation.redirects.start and impersonation.redirects.stop to your application's local landing paths. These are server-side configuration values, never accepted from request input.
Start and return
The default routes are:
POST /impersonation/{user}—impersonation.startDELETE /impersonation—impersonation.stop
Use CSRF-protected forms or your framework's request helpers. The start endpoint accepts the target's authentication identifier. The stop endpoint accepts no actor identifier: it restores only the original login recorded in the existing session.
For Blade:
<form action="{{ route('impersonation.start', $user) }}" method="POST"> @csrf <button type="submit">Impersonate user</button> </form>
Inertia requests receive a 409 location response to perform a full-page transition. Other requests receive a 303 redirect. A fresh page prevents one user's local component state or workspace subscriptions from carrying into another identity.
Banner
Blade
Add this near the top of your layout:
<x-switchback-banner class="your-banner-class" />
It renders only while impersonating and includes a CSRF-protected return form. Its message and button label come from configuration. Publish and replace the entire template with:
php artisan vendor:publish --tag=impersonation-views
Vue and Inertia
The Vue component is shipped as source and requires Vue 3. It has no Inertia or Tailwind dependency. Import it from the Composer package through your bundler, for example from resources/js/Components/AppLayout.vue:
<script setup> import { usePage } from '@inertiajs/vue3'; import ImpersonationBanner from '../../../vendor/switchback/laravel-impersonation/resources/js/ImpersonationBanner.vue'; const page = usePage(); </script> <template> <div> <ImpersonationBanner :state="page.props.impersonation" /> <slot /> </div> </template>
Share the state in your Inertia middleware:
'impersonation' => fn () => app(\Switchback\Impersonation\Impersonation::class)->banner(),
The banner uses a regular HTML return form so returning also creates a clean document. It measures its own height and sets --switchback-banner-height on the root element. It adds body padding to reserve its space; offset your fixed sidebar and sticky headers with this variable when needed.
The default slot can replace the entire contents. The button slot replaces the return button contents. Both slots receive state. Set --switchback-background, --switchback-color, and --switchback-font to customize appearance. Labels are escaped by both renderers.
For another frontend stack, Impersonation::banner() returns null or an array containing active, message, button, stopUrl, and csrfToken; render your own banner using that state.
Configuration and security
Publish impersonation-config to customize:
- The session guard, session key, authorization ability, and maximum duration (one hour by default).
- Route prefix and middleware. Routes use Laravel's
webgroup and its CSRF protection. Disable automatic routes if you register your own, retaining theimpersonation.startandimpersonation.stopnames for the built-in banners. - Protected route-name patterns, logout route names, and session keys cleared on identity transitions.
- The target display attribute, message (
:userplaceholder), and return label.
The original login remains in the session; the effective user is replaced only while handling an impersonated web request. Both boundaries regenerate the session ID and CSRF token and clear flash messages, old input, validation errors, intended redirects, and password-confirmation state. No target remember-me cookie is created, and its password and remember token are not modified.
Authorization is rechecked against the original account on each request. Missing targets, expired sessions, or revoked permission clear impersonation before the requested action runs. A missing or mismatched original session cannot be used to sign back into an arbitrary saved account. Nested impersonation is refused. Responses while impersonating are marked no-store.
The middleware runs after session initialization and before route authentication and authorization. It also preserves compatibility with auth.session. API and token guards are not supported. Impersonation applies across tabs sharing the browser session; reload other open tabs after switching identities.
Name credential-changing routes in protected_routes or apply the package middleware explicitly:
Route::post('/sensitive-action', ...)->middleware('impersonation.protect');
A configured logout route ends impersonation before the application's normal logout action runs. This signs out the original account without rotating the target account's remember token. Configure any nonstandard logout route names.
Listen for Switchback\Impersonation\Events\Started and Stopped to add application-owned auditing. Events contain only actorId and targetId. The package does not log user data, send telemetry, create database tables, or store credentials. This repository contains synthetic fixtures only; .env, credentials, databases, dependency directories, logs, IDE settings, and local lock files are ignored.
Local development
An unpublished checkout can be installed with a Composer path repository pointing to your checkout and a dev-main version override. Use a relative path in any committed application configuration.
composer install
composer test
composer format
The test suite uses Testbench and in-memory SQLite. CI tests both supported Laravel majors. Do not commit populated environment files or real test accounts. Package source and Composer metadata contain no personal author details or machine-specific paths.