Weave Code
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 Impersonate Laravel Package

lab404/laravel-impersonate

Add secure user impersonation to Laravel: let admins log in as other users for support and debugging, then easily leave impersonation. Includes middleware, routes/helpers, session-based tracking, and simple integration with your User model.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require lab404/laravel-impersonate
    php artisan vendor:publish --provider="Lab404\Impersonate\ImpersonateServiceProvider"
    
    • Publishes config/impersonate.php with default settings.
  2. First Use Case:

    • Impersonate a user in a controller:
      use Lab404\Impersonate\Facades\Impersonate;
      
      public function impersonate(User $user) {
          Impersonate::impersonate($user);
          return redirect()->intended('/dashboard'); // Redirects as the impersonated user
      }
      
    • Stop impersonation:
      Impersonate::stop();
      return redirect()->intended('/admin');
      
  3. Blade Directives (for UI):

    @impersonatable
        <button>Impersonate</button>
    @endimpersonatable
    
    @canimpersonate
        <button>Stop Impersonating</button>
    @endcanimpersonate
    
  4. Middleware Protection: Add to app/Http/Kernel.php:

    'impersonate' => \Lab404\Impersonate\Middleware\ImpersonateMiddleware::class,
    

Implementation Patterns

Core Workflows

  1. Impersonation Flow:

    • Trigger: Admin clicks "Impersonate" on a user card.
    • Action:
      Impersonate::impersonate($user)->redirectTo('/user/dashboard');
      
    • Cleanup: Use Impersonate::stop() with a redirect back to admin view.
  2. Role-Based Access:

    • Restrict impersonation to specific roles in config/impersonate.php:
      'roles' => ['admin', 'support'],
      
    • Or dynamically via middleware:
      public function handle($request, Closure $next) {
          if (!auth()->user()->hasRole(['admin'])) {
              abort(403);
          }
          return $next($request);
      }
      
  3. Dynamic Redirects:

    • Store the original URL before impersonation:
      $originalUrl = url()->previous();
      Impersonate::impersonate($user)->redirectTo($originalUrl);
      
  4. Multi-Guard Support:

    • Specify guard name:
      Impersonate::impersonate($user, 'api');
      
    • Blade directives:
      @impersonatable('api')
      

Integration Tips

  • Audit Logging: Listen to events in EventServiceProvider:

    protected $listen = [
        \Lab404\Impersonate\Events\ImpersonateStarted::class => [
            \App\Listeners\LogImpersonation::class,
        ],
    ];
    
  • Testing: Use Impersonate::impersonate() in PHPUnit:

    public function test_as_user() {
        Impersonate::impersonate($this->user);
        $response = $this->get('/dashboard');
        $response->assertSee('User Dashboard');
    }
    
  • API Impersonation: For API-only apps, create a dedicated route:

    Route::post('/impersonate', function (Request $request) {
        $user = User::find($request->user_id);
        Impersonate::impersonate($user);
        return response()->json(['message' => 'Impersonating user']);
    })->middleware('auth:api');
    
  • Session Timeout: Configure in config/impersonate.php:

    'timeout' => 900, // 15 minutes
    

Gotchas and Tips

Pitfalls

  1. Session Conflicts:

    • Issue: Impersonation may break if the original user’s session has expired.
    • Fix: Use Impersonate::impersonate($user)->remember() to persist the session.
  2. Middleware Collisions:

    • Issue: VerifyCsrfToken or ThrottleRequests may fail during impersonation.
    • Fix: Exclude impersonation routes from middleware or use except in HandleIncomingRequests:
      protected $except = [
          'impersonate/*',
      ];
      
  3. Nested Impersonation:

    • Issue: Attempting to impersonate while already impersonating throws an error.
    • Fix: Check with Impersonate::isImpersonating() before proceeding:
      if (!Impersonate::isImpersonating()) {
          Impersonate::impersonate($user);
      }
      
  4. User Provider Errors:

    • Issue: findUserById fails if the guard’s user provider is misconfigured.
    • Fix: Ensure your guard’s provider in config/auth.php is correct:
      'guards' => [
          'web' => [
              'driver' => 'session',
              'provider' => 'users', // Must match a provider
          ],
      ],
      
  5. Blade Directive Scope:

    • Issue: @impersonatable may not render if the user lacks permissions.
    • Fix: Combine with @can:
      @can('impersonate')
          @impersonatable
              <button>Impersonate</button>
          @endimpersonatable
      @endcan
      

Debugging Tips

  • Check Impersonation Status:

    dd(Impersonate::isImpersonating(), Impersonate::getImpersonator());
    
  • Log Events: Add a listener to ImpersonateStarted/ImpersonateEnded:

    public function handle($event) {
        \Log::info('Impersonation started', [
            'impersonator' => $event->user->id,
            'impersonated' => $event->impersonatedUser->id,
        ]);
    }
    
  • Clear Stale Sessions: If impersonation feels "stuck," manually clear the session:

    session()->flush();
    

Extension Points

  1. Custom User Resolution: Override findUserById in a service provider:

    public function boot() {
        Impersonate::extend(function ($app) {
            $app->bind(\Lab404\Impersonate\Contracts\ImpersonateUserProvider::class, function () {
                return new CustomUserProvider();
            });
        });
    }
    
  2. Dynamic Role Checks: Replace static role checks with a closure in config/impersonate.php:

    'roles' => function ($user) {
        return $user->isSuperAdmin() || $user->hasPermission('impersonate');
    },
    
  3. Post-Impersonation Actions: Trigger logic after stopping impersonation via an event listener:

    public function handle($event) {
        // Send notification to the impersonated user
        $event->impersonatedUser->notify(new ImpersonationEnded);
    }
    
  4. Guard-Specific Config: Extend the config for multiple guards:

    'guards' => [
        'web' => ['timeout' => 900],
        'api' => ['timeout' => 300],
    ],
    

Configuration Quirks

  • timeout Value:

    • 0 = No timeout.
    • null = Uses session lifetime (default: 2 hours).
  • redirect_to:

    • If null, redirects to the original URL.
    • If a string, uses that path (e.g., '/dashboard').
  • remember:

    • Persists the session even after browser close (default: false).
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai