Search code examples
phplaravelmiddleware

Laravel 'can' middleware return error 500 "This action is unauthorized"


i'm trying to create a website based on laravel framework. I'm stuck in permission control with Policy. This is my code: + Policies Register in App\Providers\AuthServiceProvider:

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        User::class => UserPolicy::class,
        Category::class => CategoryPolicy::class
    ];

    public function boot()
    {
        $this->registerPolicies();

        try {
            Permission::all()->each(function($permission) {
                Gate::define($permission->name, function ($user) use($permission) {
                    return $user->hasPermission($permission->name);
                });
            });
        } catch (\Exception $e) {
            Log::notice('Unable to register gates. Either no database connection or no permissions table exists.');
        }
    }
}
  • User Policy in App\Policies\UserPolicy
class UserPolicy
{
    use HandlesAuthorization;

    public function viewAny(User $user)
    {
        return true;
    }

    public function view(User $user, User $target_user)
    {
        return $user->id === $target_user->id;
    }

}
  • Api Route in routes/api.php
Route::get('/users', 'Api\UserController@getUsers')->middleware('can:view-users');
Route::get('/users/{user_id}', 'Api\UserController@getUser')->middleware('can:view-users');
Route::put('/users/{user_id}', 'Api\UserController@updateUser')->middleware('can:edit-users');
  • User Controller in App\Http\Controllers\Api\UserController
    public function getUsers(UserRequest $request) {
        $users = $this->userRepository->getAll();
        $this->authorize('view', $user);
        return response($users, 200);
    }

    public function getUser(UserRequest $request, $user_id) {
        $user = $this->userRepository->find($user_id);
        $this->authorize('view', $user);
        return response($user, 200);
    }
  • When I try to get data by using 2 url above, it returned error 500 Internal Server Error even when user is authenticated :
{
    "error": "This action is unauthorized."
}
  • I tried to log result and found that error come from middleware can or Illuminate\Auth\Middleware\Authorize.

Code line:

$this->gate->authorize($ability, $this->getGateArguments($request, $models)); in handle() function throw error above.

  • After hours searching, I could not figure out solution.

Anyone can point out my mistake?


Solution

  • Solved. After hours reading source code in library, I figured out problem. I used api guard for my app without passport module. Thus, variable $userResolver in Illuminate\Auth\Access\Gate class could not be set to authenticated user and got null value. To solve this problem, I created my own Authorize middleware instead of laravel middleware Authorize and use Auth::guard('api')->user() to get authenticated user.