# Laravel Impersonate keeps the original user in one session key

> Laravel Impersonate is a small PHP package that adds a trait, two model methods, a route macro, a protect middleware and two events, so an administrator can sign in as a customer and sign back out without losing their own identity. The mechanism is a single session key, and the default authorisation is deliberately wide open until you write two methods.

**404labfr/laravel-impersonate** — Laravel Impersonate is a plugin that allows you to authenticate as your users.

- Repository: https://github.com/404labfr/laravel-impersonate
- Website: https://marceau.casals.fr
- Stars: 2,345 · Forks: 235
- Language: PHP
- License: not declared
- Published: 2026-09-29 · Updated: 2026-09-29 · Language: en
- Canonical page: https://hysenlabs.com/projects/404labfr-laravel-impersonate

## Two model methods and one session key

The whole mechanism fits in two method calls on the user model. Auth::user()->impersonate($other_user) swaps the authenticated user for the target, and Auth::user()->leaveImpersonation() puts the original one back. Nothing is stored in the database. The package keeps the impersonator's identifier in the session under a single configurable key, which the default configuration sets to impersonated_by, and that is what makes leaving possible without asking the administrator to log in twice. It is also what the middleware and the Blade directives read. The README explains the choice against doing it yourself: Laravel's own loginAsId() performs the swap and nothing else, whereas this package adds the route macro, the redirect handling, the view directives, the events and the guard switching. The tradeoff is a dependency with a version range against roughly forty lines of your own code.

## By default every user can impersonate every other user

This is the detail to read twice before you install anything. The README states that by default all users can impersonate a user, and that by default all users can be impersonated. Nothing is denied until you add a method. To restrict who may start an impersonation you implement canImpersonate() on the user model, returning a boolean, and the documentation's own example is a check on an is_admin flag. To restrict who may be the target you implement canBeImpersonated(), with an example returning a can_be_impersonated flag. Both are model methods, so they can be as arbitrary as you like: a role check, a tenant check, a permission package. What the package does not do is guess. An application that installs it, wires the routes, and ships without those two methods has a support desk where every customer can log in as every other customer, including an administrator. The Blade directives described later read the same two methods, which is why the buttons disappear once the methods exist.

## impersonate.protect is the guardrail for the dangerous pages

Some pages must never render while someone is standing in as a customer. A stored card, a subscription page, a payout screen, anything that shows personal data the support agent has no independent reason to see. The package ships a middleware named impersonate.protect for exactly that, and the README's example is a route that refuses to run for an impersonator:

```php
Router::get('/my-credit-card', function() {
    echo "Can't be accessed by an impersonator";
})->middleware('impersonate.protect');
```

The design point is that protection is opt-in per route rather than global, so nothing is protected until you list it. That is a reasonable default for a package used across many applications, and it is also a checklist to walk before you go live. If you adopt the package, grep your routes for anything that renders financial or identity data and attach the middleware, because the package will not tell you what you forgot.

## The route macro, the guard array and the two events

If you want the built-in controller, you register a macro in your routes file under the web middleware with Route::impersonate(), or from a RouteServiceProvider. Three generated routes follow. route('impersonate', $id) takes a user identifier, route('impersonate', ['id' => $id, 'guardName' => 'admin']) is the form you need when the application runs more than one guard, with guardName defaulting to web, and route('impersonate.leave') gives you the exit URL. Two events fire around the operation: TakeImpersonation when an impersonation starts and LeaveImpersonation when it ends, and each event carries $event->impersonator and $event->impersonated as user model instances. Those events are the integration point for an audit trail, and they are the strongest argument for the package over a hand-rolled swap, because an audit record needs both the who and the what, and both are already resolved.

## Composer, one provider, one trait, then test it

Installation is three steps. Pull the package in:

```bash
composer require lab404/laravel-impersonate
```

Register the service provider at the end of the providers array in config/app.php:

```php
'providers' => [
    // ...
    Lab404\Impersonate\ImpersonateServiceProvider::class,
],
```

Then add the Impersonate trait from Lab404\Impersonate\Models to your User model, and the two methods from the README become available. To change the session key or the redirects, publish the configuration file with the tagged vendor publish command:

```bash
php artisan vendor:publish --tag=impersonate
```

The published file is small enough to read in one go. It sets session_key to impersonated_by, which is where the original user id lives, and take_redirect_to and leave_redirect_to, both defaulting to /, which accept a URI, the keyword back or a route name. The repository also ships a test suite, run with vendor/bin/phpunit, and a migrations directory, so the package has run its own integration against the versions it claims.

## Three Blade directives decide which buttons exist

The view layer is handled by three directives, and they exist for a specific reason rather than for symmetry. @canImpersonate($guard = null) wraps the link that starts an impersonation, so the button only appears for a user who passes your canImpersonate(). @impersonating($guard = null) wraps the link that leaves, and is what puts a visible exit in the interface so an administrator is never unaware they are acting as someone else. @canBeImpersonated($user, $guard = null) takes a user as its argument, which is the case the README describes: in a list of users you want a button next to each one, but not next to the currently authenticated user and not next to anyone your canBeImpersonated() rejects. All three accept an optional guard, so the same templates work on a multi-guard application without a second set of views.

## Laravel 6 to 13, an unstated licence, and a two-step release history

The support range is wide on paper: Laravel 6.x through 13.x, on PHP 7.2 or above, and the version table maps 1.7 to the 6.x through 13.x range, 1.6 to 6.x and 7.x, 1.5 to 5.8, 1.2 to 5.7 and 5.6, and 1.1 to 5.5 and 5.4. The release history is irregular in a way that tells you how to treat that range. Version 1.7.8 shipped on 2026-03-17, the previous one, 1.7.7, on 2025-02-24, and 1.7.6 on 2024-12-25, and the last push to master is 2026-03-17. So the package is maintained, but in bursts, and the project describes itself as created by MarceauKa and tghpow with contributions from the community. What is missing is a licence: the repository root has no LICENSE file, and the README does not name one, which for a package you install into a commercial application is a question to settle with the maintainers. The repository does keep a changelog.md, and it carries both a .travis.yml and a .scrutinizer.yml, so the older continuous integration configuration is still in the tree.

## Against writing the same forty lines yourself

The realistic alternative is a trait of your own: put the original id in the session under a key, add two methods to the user model, and add a route with a guard check. That is not a strawman, and for a single application it is often the better call, because you own the audit trail, the authorisation rules and the code. Where the package wins is breadth of surface. It gives you the route macro and the generated URLs, the guard switching for multi-guard applications, the three Blade directives, the protect middleware, the two events and a published configuration file, all tested against the Laravel versions it claims. A third option is to treat impersonation as a permissions concern and reach for a role package, but that solves who may impersonate, not how the session swap works, so it composes with this one rather than replacing it. The decision comes down to whether you want the feature in your codebase or in your dependencies.

## Conclusion

Adopt Laravel Impersonate if your support team needs to see the application exactly as a customer sees it and you want the buttons, the routes and the leave path already written. Do not adopt it and leave the defaults alone, because until you implement canImpersonate() and canBeImpersonated() on the user model every authenticated user in your application can impersonate every other one. Verify three things before shipping: that impersonate.protect is attached to the routes holding payment and subscription data, that the TakeImpersonation and LeaveImpersonation events are wired to your audit log rather than ignored, and that the licence suits you, because no LICENSE file sits at the repository root even though the package has been published since version 1.1, with 1.7.8 released on 2026-03-17.

## FAQ

### How do I install Laravel Impersonate?

Run composer require lab404/laravel-impersonate, add Lab404\Impersonate\ImpersonateServiceProvider::class to the providers array in config/app.php, and add the Impersonate trait to your User model.

### Does everyone have permission to impersonate by default in Laravel Impersonate?

Yes. The README states that by default all users can impersonate a user and all users can be impersonated, and you add canImpersonate() and canBeImpersonated() to the user model to change that.

### How do I stop a route from working while someone is impersonating?

Attach the impersonate.protect middleware to the route. The README's example is a /my-credit-card route that is meant to refuse access to an impersonator, which is the kind of page the middleware is for.

### How does Laravel Impersonate work with multiple guards?

The route helper accepts a guardName key, so route('impersonate', ['id' => $id, 'guardName' => 'admin']) switches guard, and guardName defaults to web. The three Blade directives also take an optional guard argument.

### Which Laravel versions does Laravel Impersonate support?

Laravel 6.x through 13.x on PHP 7.2 or above, with release 1.7 covering that range. Older combinations map to earlier releases, 1.6 for 6.x and 7.x, 1.5 for 5.8, 1.2 for 5.7 and 5.6, and 1.1 for 5.5 and 5.4.

### Can I change the session key or the redirect after impersonating?

Yes. Publish the configuration with php artisan vendor:publish --tag=impersonate, then edit session_key, which defaults to impersonated_by, or take_redirect_to and leave_redirect_to, which accept a URI, the keyword back or a route name.

## Sources

- [404labfr/laravel-impersonate on GitHub](https://github.com/404labfr/laravel-impersonate)
- [Issues](https://github.com/404labfr/laravel-impersonate/issues)
- [Project website](https://marceau.casals.fr)
- [README](https://github.com/404labfr/laravel-impersonate/blob/master/README.md)
- [Releases](https://github.com/404labfr/laravel-impersonate/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/404labfr-laravel-impersonate
