Skip to content

EloquentWorks/Masquerade

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎭 Laravel Masquerade

Tests Latest Release License

A feature-rich user impersonation package for Laravel.

Laravel Masquerade lets trusted administrators, support agents, and staff safely sign in as another user while preserving the original account, enforcing permission checks, blocking sensitive actions, limiting impersonation duration, and recording a full audit trail.

use EloquentWorks\Masquerade\Facades\Masquerade;

Masquerade::start(
    target: $user,
    reason: 'Troubleshooting support ticket #1042',
    metadata: [
        'ticket_id' => 1042,
    ],
);

Masquerade::isMasquerading();

Masquerade::stop();

✨ Highlights

  • Secure session-backed user impersonation
  • Original user restoration after masquerade sessions
  • Configurable auth guard support
  • Configurable user model for built-in routes
  • Optional built-in start and stop routes
  • Controller-driven impersonation flow
  • Model-level permission methods
  • Protection against nested impersonation
  • Protection against impersonating yourself
  • Optional required reason before starting a session
  • Session ID regeneration when starting and stopping
  • Configurable max session duration
  • Automatic expiration middleware
  • Sensitive-route blocking middleware
  • Middleware for routes that require an active masquerade session
  • Full audit logging with actor and target morph relationships
  • Reason, IP address, user agent, metadata, start time, and end time logging
  • Start, stop, denied, and expired events
  • Blade conditional directive and banner directive
  • Publishable banner view
  • Facade and global helper
  • Install and log pruning Artisan commands
  • Configurable table name, messages, redirects, and routes
  • Laravel Pint, PHPStan/Larastan, PHPUnit, Testbench, and GitHub Actions setup

πŸ“‹ Requirements

Laravel PHP Orchestra Testbench
11.15+ 8.2+ 9.x
12.x 8.2+ 10.x
13.x 8.3+ 11.x

πŸ“¦ Installation

composer require eloquent-works/masquerade
php artisan masquerade:install
php artisan migrate

The install command publishes the configuration file, migration, and banner view.

Publish only the configuration file:

php artisan vendor:publish --tag=masquerade-config

Publish only the migration:

php artisan vendor:publish --tag=masquerade-migrations

Publish only the banner view:

php artisan vendor:publish --tag=masquerade-views

Force republishing package assets:

php artisan masquerade:install --force

πŸ‘€ Prepare Your User Model

Add HasMasquerade to the account model that can perform or receive impersonation.

<?php

namespace App\Models;

use EloquentWorks\Masquerade\Traits\HasMasquerade;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Foundation\Auth\User as AuthenticatableUser;

class User extends AuthenticatableUser
{
    use HasMasquerade;

    public function canMasquerade(Authenticatable $target): bool
    {
        return $this->is_admin && ! $this->is($target);
    }

    public function canBeMasqueradedBy(Authenticatable $impersonator): bool
    {
        return ! $this->is_owner;
    }
}

By default, canMasquerade() returns false. This means nobody can masquerade until your application explicitly allows it.

🎭 Start Masquerading

use EloquentWorks\Masquerade\Facades\Masquerade;

Masquerade::start(
    target: $user,
    reason: 'Troubleshooting checkout issue',
    metadata: [
        'ticket_id' => 1042,
        'source' => 'support-panel',
    ],
);

You may also provide a specific impersonator and guard:

Masquerade::start(
    target: $user,
    impersonator: $admin,
    guard: 'web',
    reason: 'QA verification',
);

πŸ›‘ Stop Masquerading

Masquerade::stop();

When stopped, Masquerade logs the original user back in and clears the masquerade session state.

πŸ›‘οΈ Protect Routes

Block sensitive actions while masquerading:

use Illuminate\Support\Facades\Route;

Route::post('/billing/payment-method', UpdatePaymentMethodController::class)
    ->middleware(['auth', 'masquerade.block']);

Enforce automatic expiration on normal authenticated routes:

Route::middleware(['web', 'auth', 'masquerade.duration'])->group(function (): void {
    Route::get('/dashboard', DashboardController::class);
});

Require an active masquerade session:

Route::get('/support/masquerade-toolbar', SupportToolbarController::class)
    ->middleware(['auth', 'masquerade.required']);

🧭 Built-In Routes

When routes are enabled, Masquerade registers:

POST /masquerade/{user}/start
POST /masquerade/stop

Start from a Blade form:

<form method="POST" action="{{ route('masquerade.start', $user) }}">
    @csrf

    <input
        type="hidden"
        name="reason"
        value="Support ticket #1042"
    >

    <input
        type="hidden"
        name="redirect_to"
        value="{{ route('dashboard') }}"
    >

    <button type="submit">
        Masquerade as {{ $user->name }}
    </button>
</form>

Stop from a Blade form:

<form method="POST" action="{{ route('masquerade.stop') }}">
    @csrf

    <button type="submit">
        Return to my account
    </button>
</form>

Disable built-in routes if you want to provide your own controller flow:

'routes' => [
    'enabled' => false,
],

πŸͺͺ Permissions

Masquerade checks both sides of the impersonation request.

public function canMasquerade(Authenticatable $target): bool
{
    return $this->hasRole('support') && ! $this->is($target);
}

public function canBeMasqueradedBy(Authenticatable $impersonator): bool
{
    return ! $this->hasRole('owner');
}

You may disable model permission methods in the config if your application handles authorization elsewhere:

'permissions' => [
    'use_model_methods' => false,
],

🧾 Audit Logs

Every started, ended, and expired masquerade session can be recorded in masquerade_logs.

use EloquentWorks\Masquerade\Models\MasqueradeLog;

$logs = MasqueradeLog::query()
    ->latest()
    ->get();

Each log may include:

  • Masquerade UUID
  • Action: started, ended, or expired
  • Guard name
  • Impersonator morph type and ID
  • Target morph type and ID
  • Reason
  • IP address
  • User agent
  • Metadata
  • Started timestamp
  • Ended timestamp

Access the actor and target models:

$log->impersonator;
$log->target;

🚫 Sensitive Route Blocking

Use masquerade.block on routes that should never be available while impersonating another account.

Good examples include:

  • Billing changes
  • Password changes
  • Two-factor authentication changes
  • Email address changes
  • API token creation
  • Account deletion
  • Admin permission changes
Route::middleware(['auth', 'masquerade.block'])->group(function (): void {
    Route::post('/password', UpdatePasswordController::class);
    Route::post('/two-factor-authentication', EnableTwoFactorController::class);
    Route::delete('/account', DeleteAccountController::class);
});

🧩 Blade Directives

Show UI only while masquerading:

@masquerading
    <div class="alert alert-warning">
        You are currently masquerading as another user.
    </div>
@endmasquerading

Render the included banner:

@masqueradeBanner

Or include the published view manually:

@include('masquerade::banner')

πŸ“‘ Events

Masquerade dispatches events you can listen for:

EloquentWorks\Masquerade\Events\MasqueradeStarted::class;
EloquentWorks\Masquerade\Events\MasqueradeEnded::class;
EloquentWorks\Masquerade\Events\MasqueradeDenied::class;
EloquentWorks\Masquerade\Events\MasqueradeExpired::class;

Example listener registration:

use EloquentWorks\Masquerade\Events\MasqueradeStarted;
use Illuminate\Support\Facades\Event;

Event::listen(MasqueradeStarted::class, function (MasqueradeStarted $event): void {
    logger()->info('Masquerade started.', [
        'uuid' => $event->uuid,
        'guard' => $event->guard,
    ]);
});

🧰 Commands

php artisan masquerade:install
php artisan masquerade:prune

Examples:

php artisan masquerade:install --force

php artisan masquerade:prune --days=90

πŸ§ͺ Testing Your App Integration

A simple feature test might look like this:

use App\Models\User;
use EloquentWorks\Masquerade\Facades\Masquerade;
use Illuminate\Support\Facades\Auth;

it('allows support admins to masquerade as users', function (): void {
    $admin = User::factory()->create([
        'is_admin' => true,
    ]);

    $user = User::factory()->create();

    Auth::login($admin);

    Masquerade::start($user, reason: 'Support ticket');

    expect(Masquerade::isMasquerading())->toBeTrue();
    expect(Auth::user()->is($user))->toBeTrue();

    Masquerade::stop();

    expect(Auth::user()->is($admin))->toBeTrue();
});

πŸ“š Documentation

Full documentation is available in the docs directory:

βœ… Quality Checks

composer validate --strict
composer quality

Or run the tools separately:

composer format
composer analyse
composer test

πŸ” Security

Only allow highly trusted users to masquerade. Always require authorization before starting a session, consider requiring a reason, and block sensitive account, billing, authentication, and destructive routes with masquerade.block.

Masquerade regenerates the session ID when starting and stopping by default. Keep that enabled unless your application has a specific reason to disable it.

Security vulnerabilities should be reported privately according to SECURITY.md.

🀝 Contributing

See CONTRIBUTING.md and CODE_OF_CONDUCT.md.

πŸ“„ License

Laravel Masquerade is open-source software licensed under the MIT License.

About

A feature-rich Laravel impersonation package with secure session handling, audit logs, middleware, events, and Blade helpers.

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Contributors