Framework: Policy not working

Created on 30 Oct 2016  路  9Comments  路  Source: laravel/framework

  • Laravel Version: 5.3.21
  • PHP Version:
  • Database Driver & Version:

Hi all,
i'm using Policy to authorization but it's not working on all route.

Description

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.

Most helpful comment

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.

All 9 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SachinAgarwal1337 picture SachinAgarwal1337  路  3Comments

Fuzzyma picture Fuzzyma  路  3Comments

ghost picture ghost  路  3Comments

lzp819739483 picture lzp819739483  路  3Comments

RomainSauvaire picture RomainSauvaire  路  3Comments