Rretzko's avatar
Level 15

Illuminate\Auth\RequestGuard::loginUserId does not exist error

Hi - I'm trying to set up a site administration function that allows me to log in as one of my users. Here's the function I'm calling from a livewire blade file:

public function switchLogin($value)
    {
        \Illuminate\Auth\RequestGuard::loginUsingId($value,true);

        $_SESSION['loginas'] = true;
    }

I've also tried this with auth()->loginUsingId($value) and both end up with the resulting: "Method Illuminate\Auth\RequestGuard::loginUsingId does not exist" error.

Thoughts on either what I'm missing or how this should be implemented? Thanks!

0 likes
13 replies
Nakov's avatar

The issue is because indeed loginUsingId does not exists on the RequestGuard, that's a method on the SessionGuard so you are probably having an API route, in that case it won't work.

Make a route in your web.php file, and use Auth::loginUsingId() there.

Rretzko's avatar
Level 15

Thanks @nakov - I'm getting the same error, so I'm not quite there yet. Here's what I've done:

  1. Create an impersonation route in web.php with an invokable controller:
Route::get('impersonation/{user_id}', App\Http\Controllers\Siteadministration\ImpersonationController::class);

class ImpersonationController extends Controller
{
    public function __invoke($user_id)
    {
        auth()->loginUsingId($user_id);

        return redirect()->intended('dashboard');
    }
}

Thoughts on what I'm still missing. Thanks!

Nakov's avatar

Well, first off I would not do it using a get request, but a post instead.

You can add this in your component

<form action="{{ route('impersonate.login', [1]) }}" method="post">
    @csrf
    <button type="submit">Impersonate</button>
</form>

Ofcourse change 1 above with your user ID

in web.php

Route::middleware('auth')->group(function() {
    Route::get('impersonation/{user}', App\Http\Controllers\Siteadministration\ImpersonationController::class)->name('impersonate.login');
});

in the controller:

public function login(Request $request, User $user)
{
    Auth::loginUsingId($user->id);

    return redirect()->intended('dashboard');
}
Rretzko's avatar
Level 15

OK, that all makes sense, here's my structure: Component: (displays a gray button with the user's name)

<form action="{{ route('impersonate.login', [$person->user_id]) }}" method="post">
                                @csrf
                                <button class="bg-gray-400 text-black px-2 rounded" type="submit">Impersonate {{ $person->fullName }}</button>
                            </form>

Route:

Route::middleware(['auth:sanctum', 'verified'])->group(function() {

    /** SITE ADMINISTRATOR */
    Route::get('sa/', [App\Http\Controllers\Siteadministration\SiteadministratorController::class, 'index'])->name('siteadministrator.index');
    Route::post('impersonation/{user_id}', [App\Http\Controllers\Siteadministration\ImpersonationController::class, 'index'])->name('impersonate.login');
    Route::get('impersonation/destroy', [App\Http\Controllers\Siteadministration\ImpersonationController::class, 'destroy']);
...

Controller:

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;

class ImpersonationController extends Controller
{
    public function index($user_id)
    {
        Auth::loginUsingId($user_id);

        return redirect()->intended('dashboard');
    }

    public function destroy()
    {
        //TBD
    }
}

The error is thrown on the ImpersonationController at the Auth::loginUsineId($user_id) line. Is there a switch that I need to turn on or something I've forgotten to publish? Thanks!

Rretzko's avatar
Level 15

Update: I've also run this under an incognito window in case caching was an issue, but that didn't change the result.

Rretzko's avatar
Rretzko
OP
Best Answer
Level 15

@nakov : Update: I switched my Route::middleware to 'auth' from 'auth:sanctum' and that fixed the problem. Are you aware of the differences between these auth protocols? Thanks again for your responses!

2 likes
itxp's avatar

@Rretzko "Are you aware of the differences between these auth protocols?"

Can you please explain the implications? Yes... now it works as you described.

1 like
ldanielduarte's avatar

@itxp I would also be interested in this answer. I know that Sanctum is for API auth and not web. Sanctum's non-token auth is for your SPA's to be able to use the same API as mobile applications ( which use token authentication ) without needing tokens and providing the benefits of csrf and session based auth.

So, changing to auth, will decrease the security?

akhaled's avatar

There's a setUser method in Illuminate\Auth\GuardHelpers trait:

Auth::guard()->setUser(User::first());
bvfi-dev's avatar

This issue took me a while to figure out, but I finally did and I want to share what I did. This is If you have Livewire installed using Jetstream and are using the auth:sanctum

$impersonatorId = $this->currentUserId;
$target = User::findOrFail((int) $this->changeToUserId);

$sanctumGuardName = config('jetstream.guard', 'sanctum');
$defaultGuard = app('auth')->getDefaultDriver();

if ((int)$this->changeToUserId === (int)Auth::id()) {
    return;
}

Auth::guard('web')->login($target);

$sanctum = Auth::guard($sanctumGuardName);
if (method_exists($sanctum, 'setUser')) {
    $sanctum->setUser($target);
}

$hash = $target->getAuthPassword();
session([
    'password_hash_web'                  => $hash,
    "password_hash_{$sanctumGuardName}"  => $hash,
    "password_hash_{$defaultGuard}"      => $hash,
    'impersonating'                      => true,
    'impersonator_id'                    => session('impersonator_id') ?: $impersonatorId,
]);
session()->regenerate();

For switching back the same thing, but reset the session impersonator IDs and impersonating to false. Hope this helps, Im using Laravel 11, Livewire 3 and Jetstream 5 and this works just fine. Later on you can use if (session('impersonating')) for flag, if you dont want something to not be seen/used by impersonators, or store more variables in the session for more checks

Please or to participate in this conversation.