Laravel Gates, how to use them in the API route?

Viewed 3986

I'm defining my Gates for my API service in AuthServiceProvider (following the Laravel docs https://laravel.com/docs/7.x/authorization#gates):

Gate::define('view-users', function ($user) {
   return $user->hasAccess(['view-users'])
   or $user->inRole(['admin', 'operator']);
});

Here is my route:

Route::group(['namespace' => 'Api', 'middleware' => ['auth:api']], function () {
        Route::get('/users', 'UserController@listing')->name('user.listing')->middleware(['can:view-users']);
});

How can I find the get the user from the Route API file to use in the Gate?

But I don't exactly understand where this $user is coming from. In my request I am sending an Authorization Bearer token. Should I be using this within my gate to fetch the correct user from the DB? How does Laravel know who $user is?

3 Answers

The $user is the current logged in user. You do not need to provide the additional $user, Or pass the user in.

So if your app currently has a login user, that will be the one. If there is no login user the gate will return false which is protecting your resources.

You'll notice from the documentation that Laravel provides the User for you in a Gate.

It says (emphasis mine):

Gates are Closures that determine if a user is authorized to perform a given action and are typically defined in the App\Providers\AuthServiceProvider class using the Gate facade. Gates always receive a user instance as their first argument.

As Andy Song has pointed out in the comments, Laravel will resolve the User via Auth. If there is no user (not logged in, or no authentication), then, per the docs:

By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user.

If you want to trace how your user gets authenticated, your code snippet defines this middleware:

'middleware' => ['auth:api']

This uses the auth middleware, with api as a parameter. Your middleware is defined in app/Http/Kernel.php, and assuming you're using stock Laravel, it will then go on to authenticate your user, prior to your gate check taking place.

Laravel doesn't know who the $user is. You need to pass it when you use the Gate. If you pass Auth::user() as a first argument of the Gate you are using, the code you wrote will work. In other cases, you will need to fetch the user from the Database with any given input.

Related