Skip to main content

Gates vs. policies

Laravel provides two primary tools for authorization: gates and policies.
  • Gates are closures. Use them for simple checks that aren’t tied to a specific model, such as “can this user access the admin dashboard?”
  • Policies are classes. Use them to group authorization logic around a particular model or resource.
Most applications use both. Gates handle broad, model-independent checks; policies handle per-resource rules.

Gates

Gate authorization flow

Defining gates

Define gates inside the boot method of App\Providers\AppServiceProvider using the Gate facade. Gates receive the authenticated user as their first argument, plus any additional arguments you pass:

Checking gates

Call Gate::allows or Gate::denies in a controller to guard an action:
To throw an exception automatically instead of calling abort, use Gate::authorize:

Gate responses

Return a detailed Response from a gate instead of a boolean to include an error message:
Inspect the full response with Gate::inspect:

Policies

Policy authorization flow

Generating policies

Create a policy class with Artisan:
Policy classes live in app/Policies. The --model flag pre-fills CRUD method stubs.

Auto-discovery

Laravel automatically discovers policies by convention. A model at App\Models\Post is paired with a policy at App\Policies\PostPolicy. To register a policy explicitly, call Gate::policy inside AppServiceProvider::boot:

Writing policy methods

Each method receives the authenticated user and, usually, the model instance. Return a boolean (or a Response) to allow or deny:

Policy responses

Return a Response to attach a custom message to a denial:

Actions without a model instance

Some policy methods, like create, don’t operate on an existing model. Define them with only the user argument:

Guest users

By default, gates and policies return false for unauthenticated users. To allow guests through to the policy, mark the user argument as nullable:

Policy filters

To give a user unrestricted access before any other checks run, define a before method on the policy:
Returning null from before delegates to the specific policy method.

Before callback execution order

Authorizing actions using policies

Via the user model

The User model exposes can and cannot methods. Pass the ability and the model instance:
For actions without a model instance (like create), pass the policy class instead:

Via the Gate facade

Via middleware

Use the can middleware to guard routes:
For actions without a model instance:

Via Blade templates

Use @can, @cannot, and @canany directives in Blade views:

A complete example

1

Generate the policy

2

Define authorization rules

3

Protect the controller

4

Protect views

The $this->authorize method in a controller automatically throws an AuthorizationException (HTTP 403) if the check fails. You don’t need to call abort(403) manually.
Last modified on April 8, 2026