Packstub.

Impersonation

Sign in as another user to see what they see, then switch back. Impersonation is for support and debugging; for your own accounts use linked accounts.

The action

The Impersonate icon button on each row of the users table

ImpersonateAction works as a table record action or a page header action:

use Packstub\AccountSwitcher\Filament\Actions\ImpersonateAction;

// UserResource table
->recordActions([
    ImpersonateAction::make(),
])

// EditUser / ViewUser page
protected function getHeaderActions(): array
{
    return [
        ImpersonateAction::make()->record($this->getRecord()),
    ];
}

It's an icon button by default; chain the usual Action methods to change that (->button(), ->label(), ->color(), ->requiresConfirmation()).

Clicking it re-authenticates the session as the record, stores the impersonator in the session, writes an audit row, and redirects to a panel the impersonated user may access (the current one when possible — see redirectTo() in Configuration).

Authorization

The action is hidden, and AccountSwitcher::impersonate() throws, unless all of these pass:

  1. The target is not the current user.
  2. The session is not already impersonating (no nesting).
  3. canImpersonate($target) on the current user returns true — if the method exists.
  4. canBeImpersonated($by) on the target returns true — if the method exists.
  5. The plugin's canImpersonateUsing() callback returns true — if set.
class User extends Authenticatable
{
    public function canImpersonate(User $target): bool
    {
        return $this->hasRole('super-admin');
    }

    public function canBeImpersonated(User $by): bool
    {
        return ! $this->hasRole('super-admin');
    }
}

Important

Without canImpersonate() on your model, every panel user can impersonate. Add it before going to production, or use canImpersonateUsing() on the plugin.

AccountSwitcherPlugin::make()
    ->canImpersonateUsing(fn (User $by, User $target): bool => $by->can('impersonate', $target))

The banner

The impersonation banner at the bottom of the panel with a Switch back button

While impersonating, a fixed banner reads "You are signed in as Jane, impersonating from Admin" with a Switch back button. It renders at the bottom of every panel page; move it to the top or switch to the light style:

AccountSwitcherPlugin::make()
    ->banner(position: 'top', style: 'light')

The banner at the top of the page in the light style

To restyle it completely, publish the views and edit resources/views/vendor/packstub-account-switcher/banner.blade.php:

php artisan vendor:publish --tag="packstub-account-switcher-views"

The banner is a plain Blade view with inline styles so it works with any panel theme and doesn't need a custom Tailwind build.

Switching back

Switch back posts to filament.{panel}.account-switcher.switch-back, a CSRF-protected route inside the panel's authenticated group. It restores the impersonator's session, logs the end of the impersonation, and returns to the page the impersonation started from.

Programmatically:

use Packstub\AccountSwitcher\Facades\AccountSwitcher;

AccountSwitcher::isImpersonating();  // bool
AccountSwitcher::impersonator();     // ?Authenticatable
$url = AccountSwitcher::stopImpersonating();

Turning it off

AccountSwitcherPlugin::make()->impersonation(false)

The action stays hidden, the route isn't registered, and AccountSwitcher::impersonate() throws AccountSwitchDenied.

Events and log

Impersonating dispatches AccountSwitching then AccountSwitched with SwitchReason::Impersonation; switching back dispatches AccountSwitched with SwitchReason::ImpersonationEnded. Both write to the switch log. Listen to them to alert on impersonation of sensitive accounts or to invalidate API tokens.