Skip to content

Releases: EloquentWorks/Masquerade

v1.0.0 — Initial Stable Release

Choose a tag to compare

@SignalByNick SignalByNick released this 19 Jul 15:50

🎭 Laravel Masquerade v1.0.0 🎉

The first stable release of Laravel Masquerade.

Laravel Masquerade provides secure user impersonation for Laravel applications, allowing trusted administrators, support agents, and internal staff to temporarily act as another user while preserving the original user session, enforcing authorization checks, limiting impersonation duration, blocking sensitive actions, and recording detailed audit history.

This release focuses on safe impersonation workflows, auditability, session protection, developer-friendly customization, and a clean Laravel package experience.

✨ Features

  • Secure session-backed user impersonation
  • Original user restoration after masquerade sessions
  • Configurable authentication guard support
  • Configurable user model support
  • Optional built-in routes
  • Controller-driven start and stop flows
  • 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 maximum masquerade duration
  • Automatic session expiration handling
  • Sensitive-route blocking middleware
  • Middleware for routes requiring an active masquerade session
  • Request context middleware for masquerade-aware applications
  • Full audit logging with impersonator and target morph relationships
  • Reason, IP address, user agent, metadata, start time, and end time logging
  • Denied-attempt audit logging
  • Runtime metadata updates
  • Session extension support
  • Remaining and elapsed time helpers
  • Identity helper methods for impersonator and target checks
  • Typed masquerade session data object
  • Start, stop, denied, expired, and extended lifecycle events
  • Blade conditional directive
  • Blade banner directive
  • Publishable banner view
  • Facade support
  • Global helper support
  • Install command
  • Audit-log pruning command
  • Configurable routes, redirects, messages, table names, and middleware behavior
  • Laravel Pint, PHPStan/Larastan, PHPUnit, Testbench, and GitHub Actions setup
  • Expanded PHPUnit coverage
  • Full documentation with icon-led headings

🎭 Masquerading

Start a masquerade session:

use EloquentWorks\Masquerade\Facades\Masquerade;

Masquerade::start(
    target: $user,
    impersonator: $admin,
    reason: 'Helping user troubleshoot account issue.',
    metadata: [
        'ticket_id' => 'SUP-1042',
    ],
);

Stop the active masquerade session:

Masquerade::stop();

Check whether the current request is masquerading:

Masquerade::isMasquerading();

Read the current impersonator and target:

$impersonator = Masquerade::impersonator();
$target = Masquerade::target();

🔐 Permissions

Laravel Masquerade supports model-level authorization methods.

Add the HasMasquerade trait to your user model:

<?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;
    }
}

The package can prevent:

  • Non-authorized users from starting masquerade sessions
  • Users from masquerading as themselves
  • Nested masquerade sessions
  • Masquerading into protected users
  • Masquerading without a required reason

🧠 Session Context

Laravel Masquerade stores active masquerade state in the session.

The session tracks:

  • Masquerade UUID
  • Original impersonator ID
  • Original impersonator model type
  • Target user ID
  • Target user model type
  • Authentication guard
  • Reason
  • Metadata
  • Start time
  • Expiration time

Example:

$session = Masquerade::session();

$session?->uuid;
$session?->reason;
$session?->metadata;

Applications can also update session metadata at runtime:

Masquerade::updateMetadata([
    'ticket_status' => 'waiting-on-customer',
]);

Metadata may be merged or replaced depending on application needs.

⏱️ Duration Limits

Masquerade sessions can be limited by duration.

Example configuration:

'duration' => [
    'enabled' => true,
    'max_minutes' => 60,
],

Check time information:

Masquerade::elapsedMinutes();
Masquerade::remainingMinutes();

Extend a session when allowed:

Masquerade::extend(
    minutes: 15,
    reason: 'Support call is still active.',
);

Laravel Masquerade can cap extensions so sessions cannot exceed the configured maximum duration.

🧩 Middleware

Laravel Masquerade includes middleware for common protection flows.

Block sensitive routes while masquerading:

Route::middleware(['auth', 'masquerade.block'])->group(function (): void {
    Route::get('/billing', BillingController::class);
    Route::post('/password', UpdatePasswordController::class);
});

Expire masquerade sessions automatically:

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

Require an active masquerade session:

Route::middleware(['auth', 'masquerade.required'])->group(function (): void {
    Route::get('/support/masquerade/tools', SupportToolsController::class);
});

Attach masquerade context to requests:

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

🛡️ Sensitive Route Protection

Some actions should usually be blocked while masquerading.

Recommended blocked areas include:

  • Password changes
  • Email address changes
  • Two-factor authentication settings
  • Billing and payment methods
  • API token management
  • Connected accounts
  • Account deletion
  • Destructive admin actions
  • Security settings

Example:

Route::middleware(['auth', 'masquerade.block'])
    ->group(function (): void {
        Route::get('/settings/security', SecurityController::class);
        Route::get('/billing', BillingController::class);
    });

📜 Audit Logging

Laravel Masquerade includes a dedicated audit log model and migration.

Logs may include:

  • Masquerade UUID
  • Action
  • Authentication guard
  • Impersonator model
  • Target model
  • Reason
  • IP address
  • User agent
  • Metadata
  • Started timestamp
  • Ended timestamp

Example:

use EloquentWorks\Masquerade\Models\MasqueradeLog;

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

🔎 Audit Log Scopes

Laravel Masquerade includes query scopes for common audit lookups.

MasqueradeLog::query()->started()->get();
MasqueradeLog::query()->ended()->get();
MasqueradeLog::query()->denied()->get();
MasqueradeLog::query()->expired()->get();
MasqueradeLog::query()->extended()->get();

Filter by masquerade UUID:

MasqueradeLog::query()
    ->forMasqueradeUuid($uuid)
    ->get();

Filter by impersonator:

MasqueradeLog::query()
    ->forImpersonator($admin)
    ->get();

Filter by target:

MasqueradeLog::query()
    ->forTarget($user)
    ->get();

📣 Events

Laravel Masquerade dispatches lifecycle events for integration with your application.

Bundled events include:

  • MasqueradeStarted
  • MasqueradeEnded
  • MasqueradeDenied
  • MasqueradeExpired
  • MasqueradeExtended

Example listener use cases:

  • Notify security teams
  • Write external audit records
  • Track support activity
  • Send internal alerts
  • Update observability dashboards
  • Record ticket metadata

🧭 Built-In Routes

Laravel Masquerade can register optional built-in routes.

Example usage:

Route::post('/masquerade/{user}', StartMasqueradeController::class)
    ->middleware(['auth']);

Route::delete('/masquerade', StopMasqueradeController::class)
    ->middleware(['auth']);

Built-in routes support configurable redirects and safer redirect handling.

🖼️ Blade Directives

Use the Blade conditional directive:

@masquerading
    <p>You are currently masquerading as another user.</p>
@endmasquerading

Render the built-in banner:

@masqueradeBanner

Or include the publishable view manually:

@include('masquerade::banner')

🎨 Publishable Views

Publish the banner view:

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

Published views are placed in:

resources/views/vendor/masquerade/banner.blade.php

Applications can customize:

  • Banner text
  • Button styling
  • Stop masquerade form
  • Warning language
  • Layout placement
  • Icons and colors

⚙️ Configuration

Publish the configuration file:

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

Configuration supports:

  • Auth guard
  • User model
  • Route registration
  • Route middleware
  • Redirect targets
  • Required reasons
  • Maximum duration
  • Audit logging
  • Table names
  • Session keys
  • Messages
  • View behavior

Example:

'guard' => 'web',

'require_reason' => true,

'duration' => [
    'enabled' => true,
    'max_minutes' => 60,
],

'logging' => [
    'enabled' => true,
    'table_name' => 'masquerade_logs',
],

🗃️ Database Changes

Laravel Masquerade v1.0.0 includes a migration for audit logging.

The default table is:

masquerade_logs

The table stores:

id
masquerade_uuid
action
...
Read more