User impersonation
This package comes with a feature that lets you impersonate users inside tenant databases. This feature works with any identification method and any stateful auth guard — even if you use multiple.
Note: If you're currently using a non-stateful auth guard (e.g., Laravel Sanctum's guard), you can still utilize user impersonation by passing a stateful guard to
tenancy()->impersonate()
(e.g. the'web'
guard).
How it works
You generate an impersonation token and store it in the central database, in the tenant_user_impersonation_tokens
table.
Each record in the table holds the following data:
- The token value (128 character string)
- The tenant's id
- The user's id
- The name of the auth guard
- The URL to redirect to after the impersonation takes place
You visit an impersonation route that you create — though little work is needed on your side, your route will mostly just call a method provided by the feature. This route is a tenant route, meaning it's on the tenant domain if you use domain identification, or prefixed with the tenant id if you use path identification.
This route tries to find a record in that table based on the token, and if it's valid, it authenticates you with the stored user id against the auth guard and redirects you to the stored URL.
If the impersonation succeeds, the token is deleted from the database.
All tokens expire after 60 seconds by default, and this TTL can be customized — see the section at the very bottom.
Enabling the feature
To enable this feature, go to your config/tenancy.php
file and make sure the following class is in your features
part of the config:
Stancl\Tenancy\Features\UserImpersonation::class,
Next, publish the migration for creating the table with impersonation tokens:
php artisan vendor:publish --tag=impersonation-migrations
And finally, run the migration:
php artisan migrate
Usage
First, you need to create a tenant route that looks like this:
use Stancl\Tenancy\Features\UserImpersonation;
// We're in your tenant routes!
Route::get('/impersonate/{token}', function ($token) {
return UserImpersonation::makeResponse($token);
});
// Of course use a controller in a production app and not a Closure route.
// Closure routes cannot be cached.
Note that the route path or name are completely up to you. The only logic that the package does is generating tokens, verifying tokens, and doing the impersonated user log in.
Then, to use impersonation in your app, generate a token like this:
// Let's say we want to be redirected to the dashboard
// after we're logged in as the impersonated user.
$redirectUrl = '/dashboard';
$token = tenancy()->impersonate($tenant, $user->id, $redirectUrl);
And redirect the user (or, presumably an "admin") to the route you created.
Domain identification
// Note: This is not part of the package, it's up to you to implement
// a concept of "primary domains" if you need them. Or maybe you use
// one domain per tenant. The package lets you do anything you want.
$domain = $tenant->primary_domain;
return redirect("https://$domain/impersonate/{$token->token}");
Path identification
// Make sure you use the correct prefix for your routes.
return redirect("{$tenant->id}/impersonate/{$token->token}");
And that's it. The user will be redirected to your impersonation route, logged in as the impersonated user, and finally redirected to your redirect URL.
Custom auth guards
Note: The auth guard used by user impersonation has to be stateful (it has to implement the
Illuminate\Contracts\Auth\StatefulGuard
interface).
If you're using multiple auth guards, you may want to specify what auth guard the impersonation logic should use.
To do this, simply pass the auth guard name as the fourth argument to the impersonate()
method. So to expand on our example above:
tenancy()->impersonate($tenant, $user->id, $redirectUrl, 'jwt');
Customization
You may customize the TTL of impersonation tokens by setting the following static property to the amount of seconds you want to use:
Stancl\Tenancy\Features\UserImpersonation::$ttl = 120; // 2 minutes