Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I define a Gate and the code never gets called, always denies authorization #19306

Closed
s6joui opened this issue May 22, 2017 · 7 comments
Closed

Comments

@s6joui
Copy link

s6joui commented May 22, 2017

  • Laravel Version: 5.4
  • PHP Version: 7.0

Description:

In my Laravel 5.4 application users can create Projects and then Posts inside those projects.

I'm trying to prevent users from creating or editing posts inside a project they don't have access to.
To do this I implemented a Gate as explained here: https://laravel.com/docs/5.4/authorization#gates

Steps To Reproduce:

The gate checks if a user is the owner of the project.

    Gate::define('create-post', function ($user, $project) {
        Log::info($project) // !!! Never gets called
        return $project->owner_id == $user->id;
    });

On the PostController I call Gate::denies passing the project as an argument

    if (Gate::denies('create-post', $project)) {
        abort(403);
    }

The problem is the code I defined for the gate never gets called. Instead it always returns false and goes to the 403 error.
However, the code does get called if I don't pass the project as an argument but that makes it useless.

I also want to add that in this case I cannot use a Policy because the create method only takes one argument ($user) and if I try to pass the $project it fails the same way it does with the Gate.

Is this a bug? Is there another, better way to implement this funcionality? Thanks.

@Hell4Ge
Copy link

Hell4Ge commented Jun 16, 2017

Gate::define('create-post', function ($user, $project) {
Log::info($project) // !!! Never gets called
return $project->owner_id == $user->id;
});

You didn't put a semicolon after Log::info($project), which can cause error that won't be displayed for some reason. Check logs

@stevebauman
Copy link
Contributor

I also want to add that in this case I cannot use a Policy because the create method only takes one argument ($user) and if I try to pass the $project it fails the same way it does with the Gate.

You can pass as many arguments you would like to a policy method. You must use an array to do this:

PostPolicy
{
    public function create($user, $project)
    {
        return $project->owner_id == $user->id;
    }
}
public function store(Post $post)
{
    $project = Project::find(1);

    $this->authorize('create', [$post, $project]);
}

The first argument will be used to locate the correct policy, the others will be added to the arguments of the function call.

@browner12
Copy link
Contributor

do you have a policy defined for User? if you do the policy takes priority over everything else

@themsaid
Copy link
Member

Closing for lack of activity from the original author.

Thanks everyone who tried to help, but I don't think it's an issue with the core since we got no complains on this.

@browner12
Copy link
Contributor

my guess is he has a Policy defined for Projects, and that is taking authority over the gate. I ran into this confusing operation in the past. The Policies are incredibly greedy, and I have addressed this in a PR to the master branch #19120

@enriqg9
Copy link

enriqg9 commented Jul 14, 2019

@browner12 I am having this issue on L5.8, Project policy taking over.

@mennorenkens
Copy link

Just had the same issue because I forgot to add the auth:api middleware on the route. It meant that there was no authenticated user in the request, and hence the gates were never called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants