Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

VertexBuffer's avatar

"This action is unauthorized." Only on update and destroy methods.

I created a new model ExternalApiKey as well as a Controller, Policy, and Request for it. Then I defined a resource like so; Route::resource('api_keys', 'ExternalApiKeyController');

Then in my controller I'm doing;

    public function __construct()
    {
        $this->authorizeResource(ExternalApiKey::class, 'api_key');
    }

All methods work perfectly except update and destroy. Whenever it comes to those two they always give the error; This action is unauthorized. which is incredibly vague. I wish it gave more information as to WHY it is unauthorized.

Is anyone able to help out with this? Been stuck on it a few hours and can't seem to figure out what the issue is...

0 likes
8 replies
Nakov's avatar

@zyxxyzyxz Can you please show the Policy that you have written, because this does not says why it is always denied..

Based on the documentation btw:

The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument

So is the api_key sent to those two routes as well as a parameter?

VertexBuffer's avatar

@nakov

class ExternalApiKeyPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view any external api keys.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        return $user->admin;
    }

    /**
     * Determine whether the user can view the external api key.
     *
     * @param  \App\User  $user
     * @param  \App\ExternalApiKey  $api_key
     * @return mixed
     */
    public function view(User $user, ExternalApiKey $api_key)
    {
        return $user->admin;
    }

    /**
     * Determine whether the user can create external api keys.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        return $user->admin;
    }

    /**
     * Determine whether the user can update the external api key.
     *
     * @param  \App\User  $user
     * @param  \App\ExternalApiKey  $api_key
     * @return mixed
     */
    public function update(User $user, ExternalApiKey $api_key)
    {
        return $user->admin;
    }

    /**
     * Determine whether the user can delete the external api key.
     *
     * @param  \App\User  $user
     * @param  \App\ExternalApiKey  $api_key
     * @return mixed
     */
    public function delete(User $user, ExternalApiKey $api_key)
    {
        return $user->admin;
    }
}
Nakov's avatar

@zyxxyzyxz hm, this is weird, are you sure you don't have any other gate that you are using globally?

and in AuthServiceProvider you have registered the policy right?

VertexBuffer's avatar

@nakov Yeah I'm certain. I can tell the Policy is working because if I create a test and set the user as not admin on one of the requests that does work like index, it fails, and if i set them to admin, it works.

It's just those 2 specific methods update and destroy.

Nakov's avatar

@zyxxyzyxz but the index is not covered by any policy method :)

Take a look at the documentation

https://laravel.com/docs/5.8/authorization#via-controller-helpers

Scroll to the Authorizing Resource Controllers section, there is a table that maps each method from the controller with the respective policy method.

So again maybe you have a global gate / before method on the policies that allows the admin to do anything. And when the user is not admin is declined again by the global policy not by this one. You can dd() within any policy method to make sure that it really goes in there.

VertexBuffer's avatar

@nakov Just confirmed it on the store method. The policy is definitely working properly. Just not on update or destroy.

However thanks for pointing out that issue to me. That is a HUGE security issue. I don't know why they wouldn't include it.

What can I do about fixing it? Because this has just made about 90% of my application vulnerable since I was always under the impression it WAS covered by policies. I have lots of admin only controllers that index should ALSO be protected.

Nakov's avatar
Nakov
Best Answer
Level 73

@zyxxyzyxz why vulnerable? Are you storing or modifying in any way the resource within your index method? That method should just be used as a listing of the resource, but not showing any data that's not to be seen.

You can fix it by using $this->authorize() within the method I guess. Because your case is specific.

So when you say the store method works, did you added a break point within the policy like a dd() for example, or you just ran a test, which once again I am saying that it can be overriden by a gate that runs before the policies?

Plus in the policy that method does not receives any other argument except the user, try removing that and make sure if that's not causing the problem for not running?

ersad20000's avatar

Just change destroy method from this:

public function destroy($id)

to this:

public function destroy(User $user) It works for me :)

Please or to participate in this conversation.