Laravel Impersonate is a plugin that allows you to authenticate as your users.

Overview

Laravel Impersonate

Build Status Scrutinizer Code Quality

Laravel Impersonate makes it easy to authenticate as your users. Add a simple trait to your user model and impersonate as one of your users in one click.

Requirements

  • Laravel 6.x, 7.x or 8.x
  • PHP >= 7.2 or 8.0

Laravel support

Version Release
6.x to 8.x 1.7
6.x, 7.x 1.6
5.8 1.5
5.7, 5.6 1.2
5.5, 5.4 1.1

Installation

  • Require it with Composer:
composer require lab404/laravel-impersonate
  • Add the service provider at the end of your config/app.php:
'providers' => [
    // ...
    Lab404\Impersonate\ImpersonateServiceProvider::class,
],
  • Add the trait Lab404\Impersonate\Models\Impersonate to your User model.

Simple usage

Impersonate a user:

Auth::user()->impersonate($other_user);
// You're now logged as the $other_user

Leave impersonation:

Auth::user()->leaveImpersonation();
// You're now logged as your original user.

Using the built-in controller

In your routes file, under web middleware, you must call the impersonate route macro.

Route::impersonate();

Alternatively, you can execute this macro with your RouteServiceProvider.

namespace App\Providers;

class RouteServiceProvider extends ServiceProvider
{
    public function map() {
        Route::middleware('web')->group(function (Router $router) {
            $router->impersonate();
        });
    }
}
// Where $id is the ID of the user you want impersonate
route('impersonate', $id)

// Or in case of multi guards, you should also add `guardName` (defaults to `web`)
route('impersonate', ['id' => $id, 'guardName' => 'admin'])

// Generate an URL to leave current impersonation
route('impersonate.leave')

Advanced Usage

Defining impersonation authorization

By default all users can impersonate an user.
You need to add the method canImpersonate() to your user model:

    /**
     * @return bool
     */
    public function canImpersonate()
    {
        // For example
        return $this->is_admin == 1;
    }

By default all users can be impersonated.
You need to add the method canBeImpersonated() to your user model to extend this behavior:

    /**
     * @return bool
     */
    public function canBeImpersonated()
    {
        // For example
        return $this->can_be_impersonated == 1;
    }

Using your own strategy

  • Getting the manager:
// With the app helper
app('impersonate')
// Dependency Injection
public function impersonate(ImpersonateManager $manager, $user_id) { /* ... */ }
  • Working with the manager:
$manager = app('impersonate');

// Find an user by its ID
$manager->findUserById($id);

// TRUE if your are impersonating an user.
$manager->isImpersonating();

// Impersonate an user. Pass the original user and the user you want to impersonate
$manager->take($from, $to);

// Leave current impersonation
$manager->leave();

// Get the impersonator ID
$manager->getImpersonatorId();

Middleware

Protect From Impersonation

You can use the middleware impersonate.protect to protect your routes against user impersonation.
This middleware can be useful when you want to protect specific pages like users subscriptions, users credit cards, ...

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

Events

There are two events available that can be used to improve your workflow:

  • TakeImpersonation is fired when an impersonation is taken.
  • LeaveImpersonation is fired when an impersonation is leaved.

Each events returns two properties $event->impersonator and $event->impersonated containing User model instance.

Configuration

The package comes with a configuration file.

Publish it with the following command:

php artisan vendor:publish --tag=impersonate

Available options:

    // The session key used to store the original user id.
    'session_key' => 'impersonated_by',
    // Where to redirect after taking an impersonation.
    // Only used in the built-in controller.
    // You can use: an URI, the keyword back (to redirect back) or a route name
    'take_redirect_to' => '/',
    // Where to redirect after leaving an impersonation.
    // Only used in the built-in controller.
    // You can use: an URI, the keyword back (to redirect back) or a route name
    'leave_redirect_to' => '/'

Blade

There are three Blade directives available.

When the user can impersonate

@canImpersonate($guard = null)
    <a href="{{ route('impersonate', $user->id) }}">Impersonate this user</a>
@endCanImpersonate

When the user can be impersonated

This comes in handy when you have a user list and want to show an "Impersonate" button next to all the users. But you don't want that button next to the current authenticated user neither to that users which should not be able to impersonated according your implementation of canBeImpersonated() .

@canBeImpersonated($user, $guard = null)
    <a href="{{ route('impersonate', $user->id) }}">Impersonate this user</a>
@endCanBeImpersonated

When the user is impersonated

@impersonating($guard = null)
    <a href="{{ route('impersonate.leave') }}">Leave impersonation</a>
@endImpersonating

Tests

vendor/bin/phpunit

Contributors

Rationale

Why not just use loginAsId()?

This package adds broader functionality, including Blade directives to allow you to override analytics and other tracking events when impersonating, fire events based on impersonation status, and more. Brief discussion at issues/5

Licence

MIT

Comments
  • Trying to get property 'id' of non-object (View: /resources/views/includes/partials/logged-in-as.blade.php)

    Trying to get property 'id' of non-object (View: /resources/views/includes/partials/logged-in-as.blade.php)

    I am getting this error as after I deployed the project, this was working as expected prior to deployment: Trying to get property 'id' of non-object (View: /resources/views/includes/partials/logged-in-as.blade.php)

    Here is my logged-in-as.blade.php: @impersonating

    You are currently logged in as {{ auth()->user()->id }}. Return to your account.
    @endImpersonating

    invalid 
    opened by hexpit 18
  • Route(impersonate.leave)

    Route(impersonate.leave)

    When using the route(impersonate.leave), the active (impersonated) user remains unchanged, while being redirected to /.

    I can only log out the impersonated user, and log back in as admin.

    Any clue what could cause this?

    @impersonating
    <a href="{{ route('impersonate.leave') }}">Back to admin</a>
    @endImpersonating
    
    help wanted wontfix 
    opened by sandervanhooft 14
  • Implement multiple guards by @nikolvs @nenads backwards compatible

    Implement multiple guards by @nikolvs @nenads backwards compatible

    This is the same as: https://github.com/404labfr/laravel-impersonate/pull/44 With the addition of multiple users providers. Main credit to @nikolvs & @nenads

    next version 
    opened by alberto1el 9
  • Route::impersonate() returns Undefined offset: 0

    Route::impersonate() returns Undefined offset: 0

    Hi,

    I am trying to use your package and I am having some trouble with the Macro Route.

    When I incude the macro route in my routes/web.php Route::impersonate(); I get this error:

    ErrorException in Router.php line 1085: Undefined offset: 0

    Any ideas on what I am doing wrong? Kind regards

    wontfix possible bug 
    opened by gassius 9
  • impersonating twice

    impersonating twice

    Hi,

    I managed to get the impersonation working correctly, but when I am impersonating a user, i cannot directly impersonate another user without leaving impersonation first.

    So when i run: /impersonate/take/2

    All fine until I request: /impersonate/take/3

    I got the following error: Symfony \ Component \ HttpKernel \ Exception \ HttpException No message

    /home/vagrant/laravelapps/dev.contentoo.com_react/contentoo_v3/vendor/laravel/framework/src/Illuminate/Foundation/Application.php return file_exists($this->storagePath().'/framework/down'); }

    /home/vagrant/laravelapps/myapp/vendor/laravel/framework/src/Illuminate/Foundation/Application.php
           return file_exists($this->storagePath().'/framework/down');
       }
    
       /**
        * Throw an HttpException with the given data.
        *
        * @param  int     $code
        * @param  string  $message
        * @param  array   $headers
        * @return void
        *
        * @throws \Symfony\Component\HttpKernel\Exception\HttpException
        */
       public function abort($code, $message = '', array $headers = [])
       {
           if ($code == 404) {
               throw new NotFoundHttpException($message);
           }
    
           throw new HttpException($code, $message, null, $headers);
       }
    
       /**
        * Register a terminating callback with the application.
        *
        * @param  \Closure  $callback
        * @return $this
        */
       public function terminating(Closure $callback)
       {
           $this->terminatingCallbacks[] = $callback;
    
           return $this;
       }
    
       /**
        * Terminate the application.
        *
        * @return void
        */
    
    

    Is looks like the previous impersonation couldn't be removed..

    Does somebody know what i'm doing wrong or is it a bug?

    Thanks, Thijs

    help wanted 
    opened by contentoo-tvdveen 8
  • Call to a member function getKey() on null

    Call to a member function getKey() on null

    Hi

    Maybe I'm missing something, the package works perfect when I do something like this: Auth::user()->impersonate(User::find(1));

    But when I try to use the blade directive for example:

    //admin/users

    @canImpersonate < a href="{{ route('impersonate', $user->id) }}" class="btn btn-xs btn-default"> Impersonate < /a> @endCanImpersonate

    It redirect to impersonate/take/1 and show the following error:

    FatalThrowableError in ImpersonateController.php line 32: Call to a member function getKey() on null

    Could you please give me some advice to make the package works properly with blade directives?

    help wanted 
    opened by alblez 7
  • move blade directives after resolving

    move blade directives after resolving

    By using Blade::directive from your register method seems to force blade to fire its resolving, causing other packages which load their directives afterResolving to fail.

    See https://github.com/spatie/laravel-permission/issues/458, https://github.com/albertcht/invisible-recaptcha/issues/41 and related issues

    opened by bmichotte 6
  • multiple guards

    multiple guards

    Hi,

    I am using multiple guards and I want the default guard (User model) to be able to impersonate an instance of a different guard (Student guard).

    I added the trait to the Student model, but https://example.com/impersonate/take/1/view gives me a 404 error page.

    Is multi guard supported?

    Update:

    if I put Route::impersonate(); in

    Route::group(['middleware' => 'student_guest'], function() {
    	Route::get('student', 'StudentAuth\LoginController@showLoginForm');
    	//...
    	Route::impersonate();
    });
    

    I am redirected to the login page for the student

    if I put Route::impersonate(); in

    Route::group(['middleware' => 'student_auth'], function() {
    	Route::post('student/logout', 'StudentAuth\LoginController@logout');
    	//...
    	Route::impersonate();
    });
    

    I get the 404 error page.

    help wanted 
    opened by jozeflambrecht 6
  • Impact on remember_token?

    Impact on remember_token?

    I've been using this package happily on a project, except that users are all complaining that their "remember me" stopped working.

    My usual suspect was broken cookies, or bad remember_tokens in the user table, so I cleared all those, but the problem persists. The only other change was adding this package.

    Wondering if you've seen any evidence of this same symptom, or have any ideas why it would be interfering?

    Just using the default file session driver. All /config/session.php is same as standard Laravel 5.4 release defaults.

    bug 
    opened by drbyte 6
  • Extra cookies

    Extra cookies

    With the package installed, signing in creates one extra cookie, signing out creates yet another one. Those are not cleared at any point, so they stack up quite quickly.

    Is this intended?

    question 
    opened by AngelinCalu 5
  • cant impersonate more than once in multiguard setup

    cant impersonate more than once in multiguard setup

    for example lets say we have 2 guards web, driver & to activate the impersonation we use route('impersonate', ['id' => $model->id, 'guardName' => 'driver])

    we will have 2 scenarios

    • as long as we are using web, everything is working as expected
    • tryin to use any other guard ex.driver more than once will logout the user and u will be redirected to login.

    not sure what is the issue 😢

    opened by ctf0 5
  • Redirect url feature

    Redirect url feature

    It is a small improvement that will permit to pass a redirection url when it is needed. To pass a url different from the used in config file:

    Use Session::put('imp_back_url', 'CUSTOM_URL');

    before impersonate

    Example of use before impersonate:

    if($request->back_url){
          $request->session()->put('imp_back_url', $request->back_url);
    }
    
    return redirect(route('impersonate', $request->user_id));
    

    This session imp_back_url will be cleared when user leave impersonate.

    With this small improvement it is posible to pass custom redirection url when needed or use default from config if it's not passed trough session.

    It is working fine and solved my needs. I hope it's make sense.

    opened by cardei 1
  • Seeing 403's after basic Laravel 9 install

    Seeing 403's after basic Laravel 9 install

    Using Laravel 9.34.0 and stock session auth driver.

    Installed the package:

    "lab404/laravel-impersonate": "^1.7",
    

    Added Impersonate trait to app\User.php:

    use HasFactory, Notifiable, Impersonate;
    

    Added the route helper at the top of routes/web.php:

    Route::impersonate();
    

    Navigating to /impersonate/take/2 displays the "403 | Forbidden" error page. Navigating to / shows I am impersonating user 2 as expected. Navigating to /impersonate/leave again displays the "403 | Forbidden" error page. Navigating to / shows I am logged in as the original user again.

    Any idea why the impersonate routes are not redirecting and instead returning a 403?

    opened by imacrayon 0
  • Inject sandbox instance in service provider for Laravel Octane support

    Inject sandbox instance in service provider for Laravel Octane support

    This PR fixes stale instances of ImpersonateManager when using Laravel Octane. It was mentioned in #164 When I try to leave impersonalization it wouldn't work because of that issue.

    I replaced $this->manager with fresh instances of ImpersonateManager using app()->make(ImpersonateManager::class)

    opened by OstojicI 0
  • Set remember me token expire date to 1 year

    Set remember me token expire date to 1 year

    When you stop impersonating a user, the expire date of the remember token gets set to session. image

    This means that when you close the browser and the session ends, the remember me token is gone, and the user has to log in again (that is if the Laravel session expired). Setting the remember me token to a date will keep the remember token when the browser closes, and the user will still be logged in.

    opened by DanielGSoftware 3
Releases(1.7.3)
A simple Content Moderation System for Laravel 5.* that allows you to Approve or Reject resources like posts, comments, users, etc.

Laravel Moderation A simple Moderation System for Laravel 5.* that allows you to Approve or Reject resources like posts, comments, users, etc. Keep yo

Alex Kyriakidis 509 Dec 30, 2022
Laravel Users | A Laravel Users CRUD Management Package

A Users Management Package that includes all necessary routes, views, models, and controllers for a user management dashboard and associated pages for managing Laravels built in user scaffolding. Built for Laravel 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 6.0, 7.0 and 8.0.

Jeremy Kenedy 393 Nov 28, 2022
Durable workflow engine that allows users to write long running persistent distributed workflows in PHP powered by Laravel queues

Durable workflow engine that allows users to write long running persistent distributed workflows (orchestrations) in PHP powered by Laravel queues. Inspired by Temporal and Azure Durable Functions.

null 268 Dec 27, 2022
Laravel plugin to track your users logins and alert when a suspicious login occurs

Laravel Suspicious Logins Detect suspicious logins for standard Laravel authentication (base Laravel, Jetstream, etc) and notify a list of administrat

Advent Development 74 May 1, 2022
This package allows you to easily track your laravel jobs!

Trackable Jobs For Laravel This package allows you to track your laravel jobs! Using this package, you can easily persist the output and the status of

Mateus Junges 220 Dec 25, 2022
The missing laravel helper that allows you to inspect your eloquent queries with it's bind parameters

Laravel Query Inspector The missing laravel helper that allows you to ispect your eloquent queries with it's bind parameters Motivations Let's say you

Mouad ZIANI 59 Sep 25, 2022
Vandar Cashier is a Laravel package that allows you to seamlessly implement IPG and Direct Debit on your application

Vandar Cashier is a Laravel package that provides you with a seamless integration with Vandar services. Take a look at Vandar Documentation for more i

Vandar 11 Dec 14, 2022
This package provides a Logs page that allows you to view your Laravel log files in a simple UI

A simplistics log viewer for your Filament apps. This package provides a Logs page that allows you to view your Laravel log files in a simple UI. Inst

Ryan Chandler 9 Sep 17, 2022
This package allows you to easily work with NanoID in your Laravel models.

Laravel Model UUIDs Introduction Huge thanks to Micheal Dyrynda, whose work inspired me to create this package based on laravel-model-nanoid but uses

Parables Boltnoel 3 Jul 27, 2022
A Laravel package that allows you to validate your config values and environment.

Table of Contents Overview Installation Requirements Install the Package Publishing the Default Rulesets Usage Creating a Validation Ruleset Using the

Ash Allen 152 Dec 15, 2022
Laravel User Activity Log - a package for Laravel 8.x that provides easy to use features to log the activities of the users of your Laravel app

Laravel User Activity Log - a package for Laravel 8.x that provides easy to use features to log the activities of the users of your Laravel app

null 9 Dec 14, 2022
Worlds (soon to be) most advanced Anime site! Featuring Administration features and everything you need for users and yourself. The successor of aniZero.

/**********************************************************************\ | _____ H33Tx & xHENAI __ 31.01.2022| |

HENAI.eu 40 Jan 3, 2023
Your users do not always report errors, LaraBug does. LaraBug is a simple to use and implement error tracker built for the Laravel framework.

Your users do not always report errors, LaraBug does. LaraBug is a simple to use and implement error tracker built for the Laravel framework. This rep

LaraBug 197 Dec 9, 2022
Collection of the Laravel/Eloquent Model classes that allows you to get data directly from a Magento 2 database.

Laragento LAravel MAgento Micro services Magento 2 has legacy code based on abandoned Zend Framework 1 with really ugly ORM on top of outdated Zend_DB

Egor Shitikov 87 Nov 26, 2022
Save Model is a Laravel package that allows you to save data in the database in a new way.

Save Model is a Laravel package that allows you to save data in the database in a new way. No need to worry about $guarded and $fillable properties in the model anymore. Just relax an use Save Model package.

Laratips 27 Mar 2, 2022
Allows you to use Twig seamlessly in Laravel

Allows you to use Twig seamlessly in Laravel. Requirements TwigBridge >= 0.13 supports Twig 3. If you need Twig 1/2 support, use the 0.12 versions. In

Rob Crowe 877 Dec 30, 2022
A Laravel package that allows you to use multiple ".env" files in a precedent manner. Use ".env" files per domain (multi-tentant)!

Laravel Multi ENVs Use multiple .envs files and have a chain of precedence for the environment variables in these different .envs files. Use the .env

Allyson Silva 48 Dec 29, 2022
This Laravel Nova package allows you to manage media and media fields

Nova Media Hub This Laravel Nova package allows you to manage media and media fields. Requirements php: >=8.0 laravel/nova: ^4.0 Features Media Hub UI

outl1ne 25 Dec 22, 2022
Allow your users to login with FaceID/TouchID

Allow your users to login with FaceID/TouchID Allow your users to register physical authentication devices (FaceID or TouchID on iPhones & macs, finge

Miguel Piedrafita 888 Dec 31, 2022