Search code examples
phplaravelauthorizationpolicy

Laravel - Authorization Works from Controller Method only


I have setup my model policy and it seems to be working when I authorize actions from within controller actions.

// create action
public function create()
{
    $this->authorize('create', BusinessProfile::class);
    return view('business-profile.create');
}

The policy for create simply returns true or false and switching the Boolean seems to be working as I am authorized based on it.

This conforms that my policies are set up correctly.

However, instead of using the authorize method everywhere in my controller, I tried to set up the middleware in my constructor.

The Laravel documentation shows this example.

Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,App\Post');

So, I wrote this in my controller constructor.

public function __construct()
{
    $this->middleware('auth');
    $this->middleware('can:create,BusinessProfile')->only('create');
}

However, when doing this, the action is always unauthorized.

Bonus Information

I went ahead and wrote garbage code in my policy to raise a syntax error and still, I get an unauthorized response which tells me my policy is not firing at all. It could be that I have not registered my policy correctly but as mentioned above, $this->authorize(...) works as expected.


Solution

  • It seems there you used alias for your model while it requires model name. At documentation states:

    some actions like create may not require a model instance. In these situations, you may pass a class name to the middleware. The class name will be used to determine which policy to use when authorizing the action:

    You can find more information here: https://laravel.com/docs/5.4/authorization#policy-methods

    So in the controller constructor this line:

    $this->middleware('can:create,BusinessProfile')->only('creat‌​e'); 
    

    will become:

    $this->middleware('can:create,App\BusinessProfile')->only('c‌​reate');