A simple user impersonation package for Laravel with Sanctum compatibility.
- Secure user impersonation system
- Global
possess()
andunpossess()
methods - Comprehensive exception handling
- Session-based impersonation
- Sanctum compatibility
- Simple administration controls
- Visual impersonation indicator
- Easy to integrate
- This package is still in development, so use it with caution.
- It wasn't tested with all Laravel versions, only with Laravel 11.
- Install via Composer:
composer require verseles/possession
- Publish the configuration file (optional):
php artisan vendor:publish --tag=possession-config
- Add the trait to your User model:
use Verseles\Possession\Traits\ImpersonatesUsers;
class User extends Authenticatable
{
use ImpersonatesUsers;
// Add your possession logic
public function canPossess()
{
return $this->is_admin; // Your admin check logic
}
public function canBePossessed()
{
return !$this->is_admin; // Example restriction
}
}
Use the facade for direct impersonation control:
use Verseles\Possession\Facades\Possession;
// Possess a user (accepts ID, email, or User model instance)
try {
Possession::possess($targetUser);
} catch (\Verseles\Possession\Exceptions\ImpersonationException $e) {
// Handle exception
return redirect()->back()->withErrors(['impersonation' => $e->getMessage()]);
}
// Stop possessing
try {
Possession::unpossess();
} catch (\Verseles\Possession\Exceptions\ImpersonationException $e) {
// Handle exception
return redirect()->back()->withErrors(['impersonation' => $e->getMessage()]);
}
// routes/web.php
use Verseles\Possession\Facades\Possession;
Route::middleware(['web', 'auth:'.config('possession.admin_guard')])->group(function () {
Route::post('/possession/impersonate/{user}', function ($user) {
try {
Possession::possess($user);
return redirect()->route('dashboard');
} catch (\Verseles\Possession\Exceptions\ImpersonationException $e) {
return back()->withErrors(['impersonation' => $e->getMessage()]);
}
});
Route::post('/possession/leave', function () {
try {
Possession::unpossess();
return redirect()->route('admin.dashboard');
} catch (\Verseles\Possession\Exceptions\ImpersonationException $e) {
return back()->withErrors(['impersonation' => $e->getMessage()]);
}
});
});
Start Impersonation:
@if(auth()->check() && auth()->user()->canImpersonate())
<form action="{{ route('possession.impersonate', $user->id) }}" method="POST">
@csrf
<button type="submit">Impersonate User</button>
</form>
@endif
Stop Impersonation:
@include('possession::impersonating')
The package throws specific exceptions you can catch:
use Verseles\Possession\Exceptions\ImpersonationException;
try {
Possession::possess($user);
} catch (ImpersonationException $e) {
// Handle specific error types:
if ($e->getCode() === 403) {
// Authorization error
}
// General error handling
return back()->withErrors(['impersonation' => $e->getMessage()]);
}
Available exceptions:
UnauthorizedPossessException
UnauthorizedUnpossessException
TargetCannotBePossessedException
SelfPossessionException
NoImpersonationActiveException
Edit config/possession.php
after publishing:
return [
'user_model' => App\Models\User::class,
'admin_guard' => 'web',
'session_keys' => [
'original_user' => 'possession.original_user_id',
],
];
- Always protect impersonation routes with middleware
- Use separate guards for admin and regular users
- Regularly review your
canPossess()
andcanBePossessed()
logic - Never expose impersonation controls to non-administrative users
The MIT License (MIT)