-
Notifications
You must be signed in to change notification settings - Fork 34
Closed
Labels
needs more infoMore information is requiredMore information is required
Description
- Laravel Version: 11.43.0
- Nova Version: 4.27.0
- PHP Version: 8.3.17
- Database Driver & Version: Mysql 8.2
- Operating System and Version: Unrelated
- Browser type and version: Unrelated
- Reproduction Repository: Not needed
Description:
Laravel Nova does not respect nova-impersonate guard config when multiple guards using same provider and driver.
Detailed steps to reproduce the issue on a fresh Nova installation:
config/nova-impersonate.php
<?php
return [
'default_impersonator_guard' => 'nova',
'impersonator_guards' => ['nova'],Notice: In laravel < 10 this would work as Laravel Nova selects the first defined guard, but in laravel 11 the web guard is always added to the top
Related Laravel issue: laravel/framework#55165
config/auth.php
'guards' => [
'nova' => [
'driver' => 'session',
'provider' => 'users',
],
'web' => [
'driver' => 'session',
'provider' => 'users',
],
]The authGuard will always resolve to 'web' from Laravel 11 and up ...
vendor/laravel/nova/src/Http/Controllers/ImpersonateController.php
public function startImpersonating(NovaRequest $request, ImpersonatesUsers $impersonator)
{
if ($impersonator->impersonating($request)) {
return $this->stopImpersonating($request, $impersonator);
}
/** @var class-string<\Illuminate\Contracts\Auth\Authenticatable&\Illuminate\Database\Eloquent\Model> $userModel */
$userModel = with(Nova::modelInstanceForKey($request->input('resource')), function ($model) {
return ! is_null($model) ? get_class($model) : Util::userModel();
});
$authGuard = Util::sessionAuthGuardForModel($userModel);
$currentUser = Nova::user($request);
/** @var \Illuminate\Contracts\Auth\Authenticatable&\Illuminate\Database\Eloquent\Model $user */
$user = $userModel::findOrFail($request->input('resourceId'));
// Now that we're guaranteed to be a 'real' user, we'll make sure we're
// actually trying to impersonate someone besides ourselves, as that
// would be unnecessary.
if (! $currentUser->is($user)) {
abort_unless(optional($currentUser)->canImpersonate() ?? false, 403);
abort_unless(optional($user)->canBeImpersonated() ?? false, 403);
$impersonator->impersonate(
$request,
Auth::guard($authGuard),
$user
);
}
return $impersonator->redirectAfterStartingImpersonation($request);
}Because this looks for the first guard having the given driver and provider (which always will be 'web' in >= Laravel 11)
vendor/laravel/nova/src/Util.php
public static function sessionAuthGuardForModel($model)
{
if (is_object($model)) {
$model = get_class($model);
}
$provider = collect(config('auth.providers'))->reject(function ($provider) use ($model) {
return ! ($provider['driver'] === 'eloquent' && is_a($model, $provider['model'], true));
})->keys()->first();
return collect(config('auth.guards'))->reject(function ($guard) use ($provider) {
return ! ($guard['driver'] === 'session' && $guard['provider'] === $provider);
})->keys()->first();
}Solution
Always respect the default_impersonator_guard config.
Metadata
Metadata
Assignees
Labels
needs more infoMore information is requiredMore information is required