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 Jwt Impersonate Laravel Package

rickycezar/laravel-jwt-impersonate

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require rickycezar/laravel-jwt-impersonate
    

    Publish the config file:

    php artisan vendor:publish --provider="Rickycezar\LaravelJwtImpersonate\ServiceProvider" --tag="config"
    
  2. Configuration: Update config/laravel-jwt-impersonate.php to define:

    • guard_name (default: api)
    • middleware (e.g., auth:api)
    • impersonate_route (e.g., impersonate.user)
    • impersonate_middleware (e.g., can:impersonate-users)
  3. First Use Case: Add a route to trigger impersonation (e.g., in routes/api.php):

    Route::post('/impersonate/{user}', [ImpersonateController::class, 'impersonate'])->name('impersonate.user');
    

    Create a controller to handle impersonation logic:

    use Rickycezar\LaravelJwtImpersonate\Facades\Impersonate;
    
    public function impersonate(User $user)
    {
        return Impersonate::impersonate($user);
    }
    
  4. Testing: Use Postman or Laravel's HTTP tests to send a request with the target user's ID and your admin credentials:

    $response = $this->actingAs($admin)
        ->postJson('/impersonate/' . $targetUser->id);
    

Implementation Patterns

Workflows

  1. Impersonation Flow:

    • Trigger: Admin user sends a request to /impersonate/{user} with their JWT.
    • Validation: Middleware checks if the admin has permission (e.g., can:impersonate-users).
    • Execution: Package generates a new JWT for the target user, replacing the admin's token.
    • Response: Returns the new JWT (e.g., { "token": "new.jwt.token" }).
  2. Reverting Impersonation: Use the revert() method to switch back to the original user:

    public function revert()
    {
        return Impersonate::revert();
    }
    

    Add a route:

    Route::post('/revert', [ImpersonateController::class, 'revert'])->name('revert.impersonate');
    
  3. Conditional Impersonation: Extend the package to add logic (e.g., log impersonation events or restrict by user roles):

    public function impersonate(User $user)
    {
        if ($user->isRestricted()) {
            abort(403, 'Cannot impersonate restricted users.');
        }
        event(new UserImpersonated($user));
        return Impersonate::impersonate($user);
    }
    

Integration Tips

  1. JWT Middleware: Ensure your auth:api middleware uses the jwt.auth middleware from tyrimys/jwt-auth (or equivalent) for seamless token replacement.

  2. Frontend Handling:

    • Store the new JWT in localStorage/cookies after impersonation.
    • Update the UI to reflect the impersonated user (e.g., show their name/avatar).
  3. API Versioning: If using API versioning (e.g., v1), prefix routes:

    Route::prefix('v1')->group(function () {
        Route::post('/impersonate/{user}', [...]);
    });
    
  4. Rate Limiting: Protect impersonation routes with Laravel's throttle middleware to prevent abuse:

    Route::middleware(['throttle:60,1'])->post('/impersonate/{user}', [...]);
    

Gotchas and Tips

Pitfalls

  1. Token Replacement:

    • The package overwrites the existing JWT. Ensure your frontend updates the auth token immediately after impersonation.
    • If using refresh tokens, manually handle their replacement or extend the package to manage them.
  2. Middleware Conflicts:

    • If auth:api middleware runs before impersonate middleware, the original user's token may still be validated. Order matters:
      // routes/api.php
      Route::middleware(['auth:api', 'can:impersonate-users'])->post('/impersonate/{user}', [...]);
      
  3. CSRF Protection:

    • Disable CSRF for impersonation routes if using API-only auth (add to $except in VerifyCsrfToken):
      protected $except = [
          'impersonate/*',
      ];
      
  4. User Model Requirements:

    • The target user must have a valid JWT payload. If using custom claims, ensure they’re compatible with the package’s default logic.

Debugging

  1. Token Not Updating:

    • Check if the response includes the new JWT. If not, verify:
      • The impersonate method is called correctly.
      • No middleware is interfering (e.g., auth:api running too early).
    • Log the JWT payload before/after impersonation:
      \Log::info('Original user:', auth()->user());
      $response = Impersonate::impersonate($user);
      \Log::info('New user:', auth()->user());
      
  2. Permission Denied:

    • Ensure the admin user has the impersonate-users ability (or your custom gate). Test with:
      $this->actingAs($admin)
          ->postJson('/impersonate/' . $user->id)
          ->assertStatus(403); // Expected if no permission
      
  3. Route Not Found:

    • Verify the route name matches the config (impersonate_route). Use php artisan route:list to debug.

Extension Points

  1. Custom Claims: Add custom claims to the impersonated JWT by extending the Impersonate facade:

    use Rickycezar\LaravelJwtImpersonate\Facades\Impersonate;
    
    public function impersonate(User $user)
    {
        $token = Impersonate::impersonate($user);
        $token->setCustomClaim('is_impersonating', true);
        return $token;
    }
    
  2. Event Listeners: Listen for impersonation events to log activity or notify users:

    // EventServiceProvider
    protected $listen = [
        \Rickycezar\LaravelJwtImpersonate\Events\UserImpersonated::class => [
            \App\Listeners\LogImpersonation::class,
        ],
    ];
    
  3. GUI Integration: Add a button in your admin panel using Laravel Blade:

    @can('impersonate-users')
        <button onclick="impersonateUser({{ $user->id }})">Impersonate</button>
    @endcan
    

    JavaScript:

    function impersonateUser(userId) {
        axios.post(`/impersonate/${userId}`)
            .then(response => {
                localStorage.setItem('auth_token', response.data.token);
                window.location.reload();
            });
    }
    
  4. Multi-Guard Support: Extend the package to support multiple auth guards by modifying the ServiceProvider:

    // app/Providers/AuthServiceProvider
    public function boot()
    {
        $this->registerPolicies();
        Impersonate::extend('sanctum', function ($user) {
            // Custom logic for Sanctum impersonation
        });
    }
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
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