Hi all,
i'm using Policy to authorization but it's not working on all route.
1.Create default controller using
php artisan make:controller PostController --resource
2.Create policy
php artisan make:policy PostPolicy --model=Post
3.In PostPolicy return true for each action (view, create, update, delete)
public function view(User $user, Post $post)
{
return $user->id === 1;
}
4.Register policy in the AuthServiceProvider
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class,
];
5.In web.php add routes
Route::resource('post', 'PostController');
6.in PostController add authorizeResource method
public function __construct()
{
$this->authorizeResource(Post::class);
}
7.Access to URL from browser.
METHOD
[GET] _http://laravel.local:8000/post_ (post.index) ==> worked
[DELETE] _http://laravel.local:8000/post/1_ (post.destroy) ==> worked
[GET] _http://laravel.local:8000/post/create_ (post.create) ==> worked
[POST] _http://laravel.local:8000/post/create_ (post.store) ==> worked
[GET] _http://laravel.local:8000/1/edit_ (post.edit) ==> Error : This action is unauthorized.
[GET] _http://laravel.local:8000/1_ (post.show) ==> Error : This action is unauthorized.
8.in post_index.blade
@can('view', $post)
<a href="{{ route('post.show', ['post' => $post])}}">Show</a>
@endcan
@can('update', $post)
<a href="{{ route('post.edit', ['post' => $post])}}">Edit</a>
@endcan
Result : Show, Edit link is display correct. (in view check policy is correct ??)
2 routes : edit and show is not working.
Hello @Vocal
Shouldn't the 2 routes that are not working be like...
[GET] http://laravel.local:8000/post/1/edit
[GET] http://laravel.local:8000/post/1
post is missing from those 2 routes...
Also, I am unsure as to how you are getting This action is unauthorized instead of 404 Not Found. If you comment out the line having $this->authorizeResource(...)
and try dd("Post")
inside edit() or show() function, does it work?
Lastly, I am unsure as to why you are really using Policies if you are not doing something like
return $user->id == $policy->user_id;
//Instead of return $user->id === 1; Or is it just for testing purposes?
Hi @prateekkathal
This action is unauthorized is exception throw by Illuminate\Auth\Access\AuthorizationException (403 Error)
if i comment out $this->authorizeResource(...)
then inside edit() show() function working fine.
i'm using return $user->id === 1; (user logged id = 1) or return true; for testing but still error at 2 routes edit() and show()
if i using
Route::group(['prefix' => 'post', 'middleware' => 'auth'], function () {
Route::post('/', 'PostController@store')->name('post.store');
Route::get('/', 'PostController@index')->name('post.index');
Route::get('/create', 'PostController@create')->name('post.create')
->middleware('can:create,App\Post');
Route::delete('/{post}', 'PostController@destroy')->name('post.destroy')
->middleware('can:delete,post');
Route::put('/{post}', 'PostController@update')->name('post.update')
->middleware('can:update,post');
Route::get('/{post}', 'PostController@show')->name('post.show')
->middleware('can:view,post');
Route::get('/{post}/edit', 'PostController@edit')->name('post.edit');
});
instead of
Route::resource('post', 'PostController');
then post.edit route working fine but post.show still 403 error
I have found the problem.
When i pass parameter in to edit(Post $post) and show(Post $post) then it working.
I had the same issue and I can confirm the error goes away after changing the show
method signature from:
show($id)
to:
show(Post $post)
I just don't understand why that's happening. It seems like Laravel docs don't even mention the authorizeResource
method.
Same problem here, more than two years later it appears.
Looks like a note/warning could be added to the docs?
Laravel 5.7
face same problem:
with Controller call authorizeResource
public function __construct()
{
$this->authorizeResource(Model::class);
}
i see root cause, getting policy via Illuminate\Auth\Access\Gate::getPolicyFor return null for argument is Model::id's value
authorize middleware of show, edit, update and destroy are generated to "can:{ability},{route}" so it will let Illuminate\AuthMiddleware\Authorize::getModel return string id, not Model
Same here
class QueryPolicy
/**
* Determine whether the user can delete the query.
*
* @param \App\User $user
* @param \App\Query $query
* @return mixed
*/
public function delete(User $user, Query $query)
{
return $user->id === $query->user_id;
}
class QueryController
public function __construct()
{
$this->authorizeResource(Query::class);
}
class AuthServiceProvider
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Query::class => QueryPolicy::class,
];
EDIT: I had a type in my route
from this
Route::resource('queires', 'QueryController');
to this
Route::resource('queries', 'QueryController');
I have found the problem.
When i pass parameter in to edit(Post $post) and show(Post $post) then it working.
Thanks a ton dude! I was going mad trying to strictly follow proper laravel conventions.
I have found the problem.
When i pass parameter in to edit(Post $post) and show(Post $post) then it working.
I had the same issue on my user controller.
On all my controllers i also made the mistake of using a plural with the authorizeResource command since my routnames are plurals like 'domain/leases'
public function __construct()
{
$this->authorizeResource(Lease::class, 'leases');
}
changing it to
public function __construct()
{
$this->authorizeResource(Lease::class, 'lease');
}
// or
public function __construct()
{
$this->authorizeResource(Lease::class);
}
Fixed the issue
Most helpful comment
I had the same issue and I can confirm the error goes away after changing the
show
method signature from:to:
I just don't understand why that's happening. It seems like Laravel docs don't even mention the
authorizeResource
method.