Skip to content
Packstub

Installation

Requirements

  • PHP 8.2 or newer
  • Laravel 12 or 13
  • A session guard (the default web guard is fine)

1. Require the package

composer require packstub/account-switcher
php artisan account-switcher:install

The install command publishes the config file and the two migrations (linked_accounts, account_switches) and offers to run them. You can run the pieces yourself instead:

php artisan vendor:publish --tag="account-switcher-config"
php artisan vendor:publish --tag="account-switcher-migrations"
php artisan migrate

Note

The migrations reference your user model's table through config('auth.providers.users.model'). If your guard authenticates a different model, set user_model in the config file before migrating. See Configuration.

Without migrations

Only need impersonation and one-click developer logins? Skip the migrations. Those two features keep their state in the session; only linked accounts (the linked_accounts table) and the switch log (the account_switches table) need the database. Turn both off in the config file:

'features' => [
    'impersonation' => true,
    'linked_accounts' => false,
    'developer_logins' => true,
],

'log_switches' => false,

Then answer "no" when the install command offers to run the migrations (or publish the config file alone), and skip the HasLinkedAccounts trait in step 2. Either feature can come back later: run the migrations and flip the key. Without the log, the AccountSwitched event is your audit trail; see Security.

2. Prepare the user model

Add the HasLinkedAccounts trait and the two authorization hooks:

use Illuminate\Foundation\Auth\User as Authenticatable;
use Packstub\AccountSwitcher\Concerns\HasLinkedAccounts;

class User extends Authenticatable
{
    use HasLinkedAccounts;

    /**
     * Who may impersonate other users. Optional; without it any signed-in
     * user can impersonate. Add it before going to production.
     */
    public function canImpersonate(User $target): bool
    {
        return $this->is_admin;
    }

    /**
     * Who may be impersonated. Optional.
     */
    public function canBeImpersonated(User $by): bool
    {
        return ! $this->is_admin;
    }
}

The trait adds the linkedAccounts() relationship and the linkAccount() / unlinkAccount() / isLinkedTo() helpers. Leave it out if you only want impersonation.

3. Register the routes

In routes/web.php, so the session and CSRF middleware apply:

use Packstub\AccountSwitcher\Facades\AccountSwitcher;

AccountSwitcher::routes();
Route Name Who
POST account-switcher/impersonate/{user} account-switcher.impersonate signed in (auth)
POST account-switcher/switch-back account-switcher.switch-back signed in
POST account-switcher/switch account-switcher.switch signed in
POST account-switcher/developer-login account-switcher.developer-login guest, throttled 10/minute

Change the prefix or the middleware of the signed-in routes: AccountSwitcher::routes(prefix: 'admin/switch', middleware: ['auth:staff', 'verified']). Call it inside a route group to add a domain or more middleware.

4. Add the banner

Anywhere in the layout every signed-in page uses. It renders nothing unless the session is impersonating:

<x-account-switcher::banner />

The banner is fixed to the bottom of the page in the dark style; position and style in the config, or on the component (<x-account-switcher::banner position="top" style="light" />), move and restyle it. Publish the views to change the markup:

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

5. Impersonate from your users page

A form that posts to the route:

@foreach ($users as $user)
    @if (AccountSwitcher::canImpersonate(auth()->user(), $user))
        <form method="POST" action="{{ route('account-switcher.impersonate', $user) }}">
            @csrf
            <button type="submit">Impersonate</button>
        </form>
    @endif
@endforeach

Or from a controller or a Livewire component:

use Packstub\AccountSwitcher\Facades\AccountSwitcher;

AccountSwitcher::impersonate($user);

return redirect()->to(AccountSwitcher::redirectUrlFor($user));

6. Developer logins (optional)

Turn the feature on in the config, list the seeded accounts, and render the buttons on the login page:

// config/packstub-account-switcher.php
'features' => ['developer_logins' => true],
'developer_logins' => [
    'environments' => ['local'],
    'users' => ['admin@example.com', 'customer@example.com'],
],
<x-account-switcher::developer-logins />

Continue with Impersonation.