404labfr / laravel-impersonate

Laravel Impersonate is a plugin that allows you to authenticate as your users.
https://marceau.casals.fr
1.99k stars 201 forks source link

I can successfully impersonate, but leaving will log out #134

Open sathio opened 3 years ago

sathio commented 3 years ago

Hi, I'm using laravel 8 and jetstream, I'm not sure why I am able to impersonate any user I need but then when I fire route('impersonate.leave') i'm kicked to the login page. I find it odd that it can impersonate a user but can't get back to previous session. Any idea?

dhruva81 commented 3 years ago

I am also facing same issue. Did you find any solution for this?

Thanks

sathio commented 3 years ago

nope, I've decide to make my own impersonating tool, it is very limited so, not really worth sharing.

mdcass commented 3 years ago

I'm facing the same issue, any info on this?

sathio commented 3 years ago

I would say that this is abandonware

MarceauKa commented 3 years ago

No issue with Jetstream and Impersonate. If you need more info, please paste your config files here.

mdcass commented 3 years ago

Hi, i'm using the near-default config file

<?php

return [

    /**
     * The session key used to store the original user id.
     */
    'session_key' => 'impersonated_by',

    /**
     * The session key used to stored the original user guard.
     */
    'session_guard' => 'impersonator_guard',

    /**
     * The session key used to stored what guard is impersonator using.
     */
    'session_guard_using' => 'impersonator_guard_using',

    /**
     * The default impersonator guard used.
     */
    'default_impersonator_guard' => 'web',

    /**
     * The URI to redirect after taking an impersonation.
     *
     * Only used in the built-in controller.
     * * Use 'back' to redirect to the previous page
     */
    'take_redirect_to' => '/',

    /**
     * The URI to redirect after leaving an impersonation.
     *
     * Only used in the built-in controller.
     * Use 'back' to redirect to the previous page
     */
    'leave_redirect_to' => '/admin',

];
mdcass commented 3 years ago

Also note i'm using Jetstream and Fortify (both dig in to the guards I believe)

gazben commented 3 years ago

I'm also using Jetstream and I faced this issue. The problem is that the guard password session variable is not updated properly. If you use the web guard adding the value to the session manually will fix the issue:

    public function quietLogin(Authenticatable $user)
    {
        $this->updateSession($user->getAuthIdentifier());
        $this->session->put([
            'password_hash_web' =>  $user->getAuthPassword(),
        ]);

        $this->setUser($user);
    }
BKirev commented 3 years ago

I'm facing the same issue, but on the start of impersonating, when I hit the 'impersonate/take' route.

Jetstream(Inertia) + Fortify.

dmandrade commented 3 years ago

I created a fix for this issue but I didn't do a PR as it already has a pending here. Unfortunately it has not yet been approved.

Anyone who wants a simple solution can use a patch: https://gist.github.com/dmandrade/f8d7e16d32a18e250f933e9ca4705b71

To apply it automatically just install the vaimo/composer-patches package.

Save this patch file in PROJECT_ROOT/patches folder.

In composer.json add:

    "extra": {
        ...
        "patcher": {
            "search": "patches"
        }
    }

After adding the patch file and update composer.json run composer patch:apply

masterix21 commented 3 years ago

Instead of using a patcher, why don't you use the events like so?

<?php

class EventServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Event::listen(function (TakeImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonated->getAuthPassword(),
                'password_hash_sanctum' => $event->impersonated->getAuthPassword(),
            ]);
        });

        Event::listen(function (LeaveImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonator->getAuthPassword(),
                'password_hash_sanctum' => $event->impersonator->getAuthPassword(),
            ]);
        });
    }
}
dmandrade commented 3 years ago

@masterix21 No special reason. I already use patches for this type of situation until an update comes out.

masterix21 commented 3 years ago

Understandable, but - IMHO - perhaps it's safer to use events in production.

antongorodezkiy commented 2 years ago

Thank you @masterix21 This also pointed me to solution for my case where I'm using Laravel Sanctum, where instead of password_hash_web I used password_hash_sanctum

Dmitry-Allread-Return commented 2 years ago

I'm also using Jetstream and I faced this issue. The problem is that the guard password session variable is not updated properly. If you use the web guard adding the value to the session manually will fix the issue:

    public function quietLogin(Authenticatable $user)
    {
        $this->updateSession($user->getAuthIdentifier());
        $this->session->put([
            'password_hash_web' =>  $user->getAuthPassword(),
        ]);

        $this->setUser($user);
    }

Thanks a lot man!!! I spent half a day to find the core of the problem and it helped me!

jonathanoeijoeng commented 2 years ago

I face the same issue with jetstream. Where I have to put this script? So all I need to do is paste this script?

tonypartridger commented 1 year ago

Instead of using a patcher, why don't you use the events like so?

<?php

class EventServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Event::listen(function (TakeImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonated->getAuthPassword(),
            ]);
        });

        Event::listen(function (LeaveImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonator->getAuthPassword(),
            ]);
        });
    }
}

For anyone else here using jetstreams and sanctum you will need to adjust the above to:

    public function boot()
    {
        Event::listen(function (TakeImpersonation $event) {
            session()->put([
                'password_hash_sanctum' => $event->impersonated->getAuthPassword(),
            ]);
        });

        Event::listen(function (LeaveImpersonation $event) {
            session()->put([
                'password_hash_sanctum' => $event->impersonator->getAuthPassword(),
            ]);
        });
    }

within the EventServiceProvider in: App\Providers\EventServiceProvider.php

casbizz commented 1 year ago

Instead of using a patcher, why don't you use the events like so?

<?php

class EventServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Event::listen(function (TakeImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonated->getAuthPassword(),
                'password_hash_sanctum' => $event->impersonated->getAuthPassword(),
            ]);
        });

        Event::listen(function (LeaveImpersonation $event) {
            session()->put([
                'password_hash_web' =>  $event->impersonator->getAuthPassword(),
                'password_hash_sanctum' => $event->impersonator->getAuthPassword(),
            ]);
        });
    }
}

So happy with this. Works great

selfsimilar commented 1 year ago

I was in the same situation, but I found a very easy work-around. In routes/web.php, do not use the auth:sanctum middleware, just auth, e.g.:

Route::middleware([
    'auth',
    config('jetstream.auth_session'),
    'verified',
])->group(function () {
    Route::impersonate();
});

Use auth:sanctum for the rest of your routes. This solved being getting logged out when leaving impersonation.

aarreedd commented 1 year ago

I was in the same situation, but I found a very easy work-around. In routes/web.php, do not use the auth:sanctum middleware, just auth, e.g.:

Route::middleware([
    'auth',
    config('jetstream.auth_session'),
    'verified',
])->group(function () {
    Route::impersonate();
});

Use auth:sanctum for the rest of your routes. This solved being getting logged out when leaving impersonation.

If you don't need auth:sanctum (which is most people), then this is the right solution.