syedabdulbaqi's avatar

Lumen Policies Middleware

I have successfully implemented policies for my Model class. Policy verification is working fine within the controller:

    public function show(User $user, Student $student)
    {
        return $user->school_id === $student->school_id;
    }
$request->user()->can('show', $student)

But middleware implementation for policies is not working, and I am always getting Unauthorised message.

	$router->get('/students/{student}', [
		'middleware' => ['scope:admin,moderator,teacher', 'can:show,student'], 
		'uses' => 'StudentController@show'
	]);
$app->routeMiddleware([
    'auth' => App\Http\Middleware\Authenticate::class,
    'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
    'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
    'can' => Illuminate\Auth\Middleware\Authorize::class,
]);

Spend a lot of time debugging the issue, and found out that function "guessPolicyName" under

\vendor\illuminate\auth\Access\Gate.php

is returning incorrect policy => .\Policies\6Policy (should have been StudentPolicy)

The numeric digit (6) is the student route parameter. Any help would be appreciated.

0 likes
5 replies
bobbybouwmann's avatar

I think it doesn't understand the route model binding here. Try this instead

$router->get('/students/{student}', [
    'middleware' => ['scope:admin,moderator,teacher', 'can:show,App\Student'], 
    'uses' => 'StudentController@show'
]);

student in this case indeed points to the number, but the middleware doesn't know it's supposed to be a student object. If you are explicit about it, it should work.

Documentation: https://laravel.com/docs/7.x/authorization#via-middleware

syedabdulbaqi's avatar

Dear @bobbybouwmann I tried your suggestions and now I am getting too few arguments on policy method.

Too few arguments to function App\Policies\StudentPolicy::show(), 1 passed in \vendor\illuminate\auth\Access\Gate.php on line 706 and exactly 2 expected (500 Internal Server Error)

I was doing some digging in laravel docs and noticed that Implicit model binding is required in order to pass model to policy method.

https://laravel.com/docs/7.x/authorization#via-middleware

I am not sure how I can do that with my current route

	$router->get('/students/{student}', [
		'middleware' => ['scope:admin,moderator,teacher', 'can:show,student'], 
		'uses' => 'StudentController@show'
	]);

Any help would be appreciated.

bobbybouwmann's avatar

You have the User and Student in the controller method, but your route only has the student parameter. You can't have both of them. It can only be one

public function show(Student $student)
{

}
syedabdulbaqi's avatar

Dear @bobbybouwmann

The show method in policy is required to check if user can view student record or not, thats why it is required to pass User object. In fact examples in laravel docs also show passing of User object in policy method.

https://laravel.com/docs/7.x/authorization#generating-policies

The issue seems to be inability of Implicit model binding in Lumen, due to which middleware in route is unable to injecting model into policy method.

Just to be sure, I tried the same setup with fresh laravel installation and it worked.

bobbybouwmann's avatar

Aah sorry, I thought this was the controller method :see_no_evil:

This is indeed an issue with Lumen... Not sure if there is a workaround for it.

Please or to participate in this conversation.