Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Multitenancy Impersonate Laravel Package

victoryoalli/laravel-multitenancy-impersonate

Laravel package for impersonating users in multi-tenant applications. Let admins act as a tenant user while keeping tenant context and isolation intact, with simple start/stop impersonation flows for support, debugging, and administration.

View on GitHub
Deep Wiki
Context7

Getting Started

The package lets an authenticated user (typically a central/super-admin) log in as another user — including a user that lives in a different tenant database and on a different domain — then return to their own session. v2.3.0 adds no runtime code; it ships an AI assistant skill, so existing installs upgrade with composer update victoryoalli/laravel-multitenancy-impersonate and nothing else.

  1. Install and publish:
    composer require victoryoalli/laravel-multitenancy-impersonate
    php artisan vendor:publish --tag="multitenancy-impersonate-config"
    php artisan vendor:publish --tag="multitenancy-impersonate-migrations"
    php artisan migrate
    
    The migration creates the impersonation token table. Confirm which connection it runs on — see Gotchas.
  2. Look first at the config file (config/multitenancy-impersonate.php). Almost every question you will have (which user model, which guard, token lifetime, route/middleware names, rate-limit keys) is answered there, not in the README.
  3. Then look at the new Boost skill — resources/boost/skills/laravel-multitenancy-impersonate-development/SKILL.md, delivered from vendor/victoryoalli/laravel-multitenancy-impersonate/resources/boost/skills/. If you use Laravel Boost (or any editor that reads .ai/skills/), re-run Boost's install/sync so the skill is copied into your project, commit it, and point your agent at it. It is the most accurate description of CanImpersonate, ImpersonateToken, config keys, rate limiting, security and testing available to a model, and it beats letting the agent guess at config key names.
  4. Wire up your User model: implement/use the CanImpersonate contract or trait, and add an authorization gate (see below) so only real admins can start an impersonation.
  5. First use case to get working end to end: an admin on the central domain clicks "Impersonate" next to a tenant user → the user is redirected to the tenant's domain and authenticated as that user → a "Leave impersonation" action restores the original admin session back on the central domain.

Implementation Patterns

Trait/contract on the user model. Put CanImpersonate on whichever model represents the impersonator (usually the central User), not on the tenant user model. If your central and tenant users are the same class, guard the capability with a role/permission check rather than the trait alone.

The token handoff, not a session copy. Cross-domain impersonation cannot share a session cookie, which is why the package mints an ImpersonateToken and redirects with it. Day-to-day this means: generate the token in the central context, redirect to the tenant URL, and let the package's middleware consume the token once and log the user in on the tenant guard. Treat the token as a short-lived, single-use credential — the same class of secret as a password-reset link.

Tenant bootstrapping order. With stancl/tenancy (or similar), identify and initialize the tenant before the token is validated and the user is resolved. The usual shape:

Route::middleware(['web', InitializeTenancyByDomain::class, PreventAccessFromCentralDomains::class])
    ->group(base_path('routes/tenant.php'));

The package's impersonation routes/middleware need to sit on the tenant side for consumption but be reachable from the central side for the redirect. Follow the config's route registration rather than hand-rolling URLs.

Rate limiting. Configure throttling in the package config and back it with a shared cache store (Redis, database). This is the main defence against token brute-forcing, so do not leave it on array or per-tenant file cache.

Audit trail. Whatever you do, log it: impersonator id, target id, tenant id, timestamp, IP. If the package emits events or notifications, listen for them in an EventServiceProvider; otherwise wrap the redirect in your own controller action so you have a single place to record intent.

Testing patterns. Feature-test both halves of the flow: an authorized admin receives a redirect containing a token; visiting the token URL authenticates as the target user ($this->assertAuthenticatedAs($target)); a second use of the same token fails; an expired token fails; an unauthorized user gets 403. Freeze time ($this->travel()) rather than sleeping for TTL tests. For the redirect assertions, use assertRedirectContains() instead of exact URL matching, since the token is random.

AI-assisted workflow (new in 2.3.0). With the skill installed, ask the agent to draft the gate, the leave-impersonation controller, and the tests against the skill's documented key names, then diff its output against config/multitenancy-impersonate.php. It is reliable for shape (which trait, which model, which middleware) and needs verification for values (your app's guard and connection names).

Gotchas and Tips

  • Token table location is the #1 failure. The impersonate_tokens table must live somewhere readable before tenant initialization — i.e. the central connection. If the migration ran inside the tenant context, tokens are written to a tenant database and the consuming request (which has not yet initialized that tenant) will never find them. Symptom: a valid-looking redirect that lands on the login page with no error.
  • Guard mismatch fails silently. If the config's guard does not match the guard your tenant users authenticate against, the login "succeeds" but the user is unauthenticated on the next request. Verify with auth()->guard(config('multitenancy-impersonate.guard')) in a tinker session inside a tenant context.
  • Shared cache for rate limiting. Central and tenant domains are separate cookie/host contexts; a file or array cache makes limits effectively per-domain and resets between requests. Use Redis.
  • Prune expired tokens. They accumulate forever otherwise. If ImpersonateToken supports Prunable, add it to the model:prune schedule; if not, add your own daily command.
  • Do not rely on the session round-trip. Anything you stash in the session before redirecting (session('impersonator_id')) is on the central domain's cookie and will not be visible on the tenant domain. Restore the original session only after the redirect back to the central domain, keyed by something server-side.
  • Authorization is yours, not the package's. Define an explicit gate and apply it to the impersonate action. At minimum: block impersonating across tenants, block impersonating other admins/super-admins, and consider disabling entirely outside local/staging.
  • Config caching quirks. Run php artisan config:cache after editing the config; in tests use config()->set() in setUp() rather than editing the published file. Older tutorials reference key names that may not exist in your installed version — trust the shipped config file.
  • The Boost skill is versioned with the package. After any upgrade, re-sync it. Stale skills are worse than no skill: a model will confidently write code against v2.2 key names while you are on v2.3.
  • Extension points are the config's model bindings and route/middleware registration: swap the ImpersonateToken model for a subclass if you need extra columns (reason, ticket id) for auditing, and override the routes if you need a policy check inside the controller.
  • Upgrade 2.2 → 2.3 is additive — no migrations, no signature changes. If you are coming from 2.x earlier than 2.2, read the intermediate changelogs before assuming the config keys are unchanged.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings