Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Impersonator Laravel Package

arcanedev/laravel-impersonator

Impersonate users in Laravel with a simple, secure API for starting and stopping impersonation sessions. Lightweight package with middleware and Blade helpers for seamless user switching.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require arcanedev/laravel-impersonator

The service provider (Arcanedev\LaravelImpersonator\Providers\LaravelImpersonatorServiceProvider) and the Impersonator facade are auto-discovered on Laravel 5.5+. Then publish the config so you can see what knobs exist before writing any code:

php artisan vendor:publish --provider="Arcanedev\LaravelImpersonator\Providers\LaravelImpersonatorServiceProvider"

Where to look first

  1. config/laravel-impersonator.php — this is the real API surface. It controls the user model class, the route prefix/middleware for the built-in take/leave endpoints, and the session key used to stash the impersonator's original ID.
  2. src/Impersonator.php — the facade root. Expect take($user), a "leave"/"stop" method, and status checks like isActive()/isImpersonating(). The README is thin, so read the class.
  3. src/Traits/ — an Impersonatable (or similarly named) trait you add to your User model so it can answer "is this user being impersonated?"
  4. src/Http/ — the built-in controller/middleware behind the packaged routes.

First use case

The canonical one: a support/admin user clicks "Login as this customer" from your admin panel, sees the app exactly as the customer does, and a persistent banner offers "Return to my account". Minimal wiring:

// User model
use Arcanedev\LaravelImpersonator\Traits\Impersonatable;

class User extends Authenticatable
{
    use Impersonatable;
}
// Admin controller
public function impersonate(User $user)
{
    abort_unless(auth()->user()->can('impersonate'), 403);

    Impersonator::take($user);

    return redirect()->route('dashboard');
}

Keep the config's user_model pointing at the same class you put the trait on, otherwise the guard swap will silently fail or throw a ModelNotFoundException.

Implementation Patterns

Authorization belongs outside the package. The package only swaps the guard; it does not decide who may impersonate. Put the policy check in your own controller/middleware and keep the packaged routes behind auth + your admin gate:

Route::middleware(['auth', 'can:impersonate'])->group(function () {
    Route::get('impersonate/{user}', [ImpersonationController::class, 'take'])->name('impersonate.take');
    Route::get('impersonate/leave',  [ImpersonationController::class, 'leave'])->name('impersonate.leave');
});

Banner pattern. Every layout should render a persistent strip while impersonation is active, with the "leave" link. Blade:

@if (Impersonator::isActive())
    <div class="alert alert-warning">
        Impersonating <strong>{{ auth()->user()->name }}</strong>.
        <a href="{{ route('impersonate.leave') }}">Return to my account</a>
    </div>
@endif

If the package ships @impersonating / @endImpersonating directives, prefer them only after checking src/Providers — the directive list is easy to verify and easy to be wrong about.

Wrap sensitive actions. A ProtectFromImpersonation middleware (or your own) on routes like password change, billing, account deletion, and API-token creation is the single most valuable integration:

// app/Http/Middleware/BlockWhileImpersonating.php
public function handle($request, Closure $next)
{
    abort_if(Impersonator::isActive(), 403, 'Not available while impersonating.');
    return $next($request);
}

Apply it by group, not route-by-route — new routes then inherit the protection by default.

Audit logging. Fire-and-forget impersonation is a compliance problem. Log both directions, keyed to the original user:

Log::info('impersonation.start', [
    'actor'   => auth()->id(),          // the impersonator
    'target'  => $user->id,
    'ip'      => request()->ip(),
]);

Wrap this in a small service or an event listener so both the controller and the leave action call the same code.

Testing pattern. In feature tests, avoid hitting the impersonation HTTP routes unless you're testing them; use the facade or session key directly and assert on behavior:

public function test_impersonated_user_cannot_change_email(): void
{
    $admin = User::factory()->admin()->create();
    $user  = User::factory()->create();

    $this->actingAs($admin);
    Impersonator::take($user);

    $this->put('/settings/email', ['email' => '[email protected]'])
         ->assertForbidden();   // guarded by your middleware
}

Then a second test that asserts auth()->id() === $admin->id after "leave" — that round-trip (target → back to original) is where impersonation implementations break most often.

Route model binding + signed URLs. If you use the packaged take route, pass the user via route model binding and consider adding Laravel's signed middleware to the URL so links can't be shared/screenshotted into a privilege escalation.

Gotchas and Tips

  • It is session-state, not a guard. Impersonation is stored in the session and read back per-request. Anything running without the web session middleware (API routes, queued jobs dispatched during impersonation, artisan commands) will not see the impersonated user. Jobs should be dispatched with an explicit user ID, not rely on auth().
  • The session driver matters in tests. With SESSION_DRIVER=array, state survives within a single test request chain but not across simulated separate requests. If assertions fail mysterically in tests, switch to database/file for the test suite or assert on the facade in-process.
  • Nested impersonation. Decide explicitly whether admin A impersonating B, then B-triggered flow impersonating C, is legal. Most implementations only store one "original user" key, so a second take() either overwrites or is rejected. Guard it: abort_if(Impersonator::isActive(), 403);
  • "Remember me" and password confirmation. After returning to the admin account, Auth::user() is correct but a stale remember_token, a password.confirm timeout, or a cached Auth::user() in a service provider can disagree. If you hit this, re-resolve the guard (Auth::forgetGuards() in older Laravel) after leave.
  • Package age. Last release was December 2020 — Laravel 8 era. Verify it installs against your Laravel version; expect to constrain laravel/framework or fork it. With only 7 stars and 0 dependents there is effectively no maintenance, so budget for vendoring (vcs repository entry or a path repo) rather than assuming upstream fixes. If the only thing you need is session()->put('impersonator', $id) plus a guard swap, ~40 lines of your own code is a legitimate alternative and removes the dependency risk entirely.
  • Don't impersonate yourself. It sounds silly, but self-impersonation leaves a dangling marker in the session that produces a confusing "return to my account" loop. abort_if(auth()->id() === $user->id, 422);
  • CSRF on the leave route. If you make leave a POST, the banner link needs a form or @method/@csrf. If you make it GET, note that a prefetch/scan can silently end an impersonation session — harmless, but confusing to the admin who clicked away.
  • Extension point worth knowing: the config's user_model and route settings mean you can repoint the package at a tenant-scoped model or an admin guard without touching vendor code. That's usually the right lever when the package doesn't do what you need — change config, add your own controller, and only call take()/leave from it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast