Skip to main content

Authentication vs. authorization

Authentication verifies “who” a user is. Signing in is the canonical example. Authorization decides “what” that user is allowed to do. For example, you might let users edit only their own posts, or restrict configuration changes to administrators. Once you’ve implemented sign-in through authentication, authorization is your next step.
Laravel’s authorization features offer two approaches: gates and policies. Which to use depends on your use case.
How to choose

Gates

Gates are simple closure-based authorization checks. They’re well suited to permission checks that aren’t tied to a particular model.

Authorization flow with gates

Defining a gate

Define gates in the boot method of App\Providers\AppServiceProvider using Gate::define().
A gate closure always receives the currently authenticated user as its first argument. Additional information — such as the target model — can be passed as further arguments.

Checking permissions with a gate

To check permissions in a controller, use Gate::allows() or Gate::denies().

Throwing exceptions with Gate::authorize()

Use Gate::authorize() to automatically return a 403 response when the user is unauthorized. You can skip the manual abort(403).
When unauthorized, Gate::authorize() throws Illuminate\Auth\Access\AuthorizationException. Laravel automatically converts it into a 403 HTTP response.

Administrator bypass (the before method)

To grant administrators every permission, use Gate::before().
If the before closure returns anything other than null, that result becomes the final permission decision. Returning null (or nothing) falls through to the normal gate check.

@can / @cannot in Blade templates

The @can and @cannot directives make it easy to run gate checks in your templates.

Policies

A policy is a class that groups authorization logic related to a particular model. For managing create, view, update, and delete permissions on a Post model, a policy is a better fit than a gate.

Authorization flow with a policy

Generating a policy

Use the make:policy Artisan command to generate a policy class.
Use the --model option to scaffold a policy that includes every CRUD method for that model.
app/Policies/PostPolicy.php is generated.

Model and policy auto-discovery

By default, Laravel automatically discovers policies based on a naming convention.
  • Model: app/Models/Post.php
  • Policy: app/Policies/PostPolicy.php
As long as you follow the convention, you don’t need to register the policy yourself.
If you deviate from the naming convention or want to register a policy manually, use Gate::policy() in the boot method of AppServiceProvider.
In Laravel 13, you can also register a policy declaratively by attaching the #[UsePolicy] attribute to the model.

Implementing policy methods

A policy generated with the --model option includes methods that correspond to the standard CRUD actions.

Administrator bypass (the before method)

Policies also support a before method that grants administrators every permission.
The before method is invoked only when a matching method exists on the policy class. For example, if there is no update method, before is not called for update.

Order of before callbacks

Using policies from controllers

The authorize() method

Laravel controllers include an authorize() helper method (when you’re not extending the base controller, use Gate::authorize() instead).

Registering RESTful policies in bulk with authorizeResource()

Calling authorizeResource() in the constructor automatically wires each controller action to the corresponding policy method.
Mapping between controller actions and policy methods:
With authorizeResource(), you no longer need to write an individual authorize() call in each action. It’s especially convenient when paired with RESTful resource controllers.

Authorization via middleware

To perform authorization at the route level, use the can middleware.
A shorter form with the can method:

Using policies in Blade templates

Once a policy is registered, Blade’s @can / @cannot directives automatically use it.

Practical example: managing blog post permissions

Here’s how to implement “only the author can edit or delete their own posts” in a blog application.
1

Generate the policy

2

Implement the policy methods

3

Add authorizeResource() to the controller

4

Add permission checks to Blade templates

Summary

  • Gates: simple permission checks that aren’t tied to a model — such as access to an admin dashboard or permission to change global settings.
  • Policies: managing CRUD permissions for a model. Create a policy class for each resource such as Post, Order, or Comment.
Last modified on August 2, 2026