I have created a resource controller for an API endpoint. I have also created a corresponding policy for the model.
If I do a per method authorization check using
$this->authorize('delete', $asset);
then it works as expected. But if I add the following to the construct, I always get a 403 forbidden. Not sure what I am missing as the following should apply the authorization for all methods.
$this->authorizeResource(Asset::class, 'asset');
This is what my route looks like:
Route::group(['middleware' => ['auth:api']], function () {
Route::Resource('asset', 'AssetsApiController');
});
My policy is registered like this:
protected $policies = [
Asset::class => AssetPolicy::class,
];
My policy method for deleting is
public function delete(User $user, Asset $asset)
{
return true;
}
The API controller constructor looks like this:
public function __construct()
{
$this->authorizeResource(Asset::class,'asset');
}
The API controller method is
public function destroy($assetID)
{
$asset = Asset::findOrFail($assetID);
$asset->delete();
}
And my routes are
| GET|HEAD | api/asset | asset.index | App\Http\Controllers\AssetsApiController@index | api,auth:api |
| POST | api/asset | asset.store | App\Http\Controllers\AssetsApiController@store | api,auth:api,can:create,App\Asset |
| GET|HEAD | api/asset/create | asset.create | App\Http\Controllers\AssetsApiController@create | api,auth:api,can:create,App\Asset |
| PUT|PATCH | api/asset/{asset} | asset.update | App\Http\Controllers\AssetsApiController@update | api,auth:api,can:update,asset |
| DELETE | api/asset/{asset} | asset.destroy | App\Http\Controllers\AssetsApiController@destroy | api,auth:api,can:delete,asset |
| GET|HEAD | api/asset/{asset} | asset.show | App\Http\Controllers\AssetsApiController@show | api,auth:api,can:view,asset |
| GET|HEAD | api/asset/{asset}/edit | asset.edit | App\Http\Controllers\AssetsApiController@edit | api,auth:api,can:update,asset |
| GET|HEAD | assets | | App\Http\Controllers\AssetsController@index | web |
I guess I am missing something but I can't see it, the gate is being shown as denied in Telescope. the only strange thing is that the serveNova
middleware seems to be the source of the issue.
Time May 8th 2019, 10:51:37 AM (14m ago)
Hostname core-hosp
Ability delete
Result denied
Location /home/vagrant/code/nova/src/Http/Middleware/ServeNova.php:25
Request View Request
Tags Auth:1
I've described my lessons learn with this tiring problem here: https://github.com/laravel/framework/issues/22847#issuecomment-521308861. Maybe somebody will find it useful.
I had the same issue and resolved it by changing the signature of the controller methods.
By default controllers receive an integer $id
to reference the model, while policies receive directly the model instance. My intuition is that the mapping can't be made between the controller and the policy.
So, I suggest to try changing your controller method to:
public function destroy(Asset $asset)
{
$asset->delete();
}
I don't know if it's a bug ? I didn't find docs about these method type signature conventions.
Updated on May 2021:
You can keep the $id
as the default param, as you can allow the mapping b/t the controller and the policy by putting the authorization call after the finding the relevant model instance, like this:
public function destroy($id)
{
$post = Post::find($id);//post instance is created b/4 going through policy.
$this->authorize('delete', $post);
$post->delete();
return Post::orderBy('created_at', 'desc')->paginate(3);
}
I found that getting the Model identifier parameter correct for authorizeResource was very fiddly. When the parameter is missing or not passed properly, the step before the Policy throws the error (not the Policy itself because the request never makes it to the Policy). In my case, that meant my CheckUserActive middleware was throwing the error, even though the mistake was in the Construct function of the Controller (not the Middleware). A few notes on the parameter that AuthorizeResource is looking for:
For example:
$this->authorizeResource(Model::class, 'parameter');
I solved this problem by removing the second parameter :
public function __construct()
{
$this->authorizeResource(Admin::class);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With