Authorization: Gates & Policies
Authentication asks “who are you?” — authorization asks “are you allowed to do this?”. Control exactly what each user can do.
What you will learn
- Tell authentication and authorization apart
- Write a Gate for a simple check
- Write a Policy to protect a model’s actions
Two different questions
It is easy to mix these up, so let us define them clearly:
- Authentication = "who are you?" — logging in proves your identity. (You did this with Breeze.)
- Authorization = "are you allowed?" — once we know who you are, may you edit *this* post, or delete *that* product?
A logged-in user should usually only edit their own posts, not everyone’s. Laravel gives you two tools for these rules: Gates (for simple, one-off checks) and Policies (for organising all the rules about one model).
Gates — a simple yes/no rule
A Gate is a small closure that returns true or false. Define gates in a service provider’s boot() method. Here is one that allows only admins:
// in a service provider's boot() method
use Illuminate\Support\Facades\Gate;
Gate::define('access-admin', function ($user) {
return $user->is_admin === true;
});The gate is named access-admin. Laravel passes the current $user in automatically; the closure returns true only if that user is an admin. Now you check the gate anywhere:
// in a controller
if (Gate::allows('access-admin')) {
// show the admin dashboard
}
// in Blade
@can('access-admin')
<a href="/admin">Admin Panel</a>
@endcanGate::allows('access-admin') returns true or false for the logged-in user. In Blade, @can('access-admin') ... @endcan shows its contents only if the user passes — so non-admins never even see the admin link.
Policies — all the rules for one model
When a model has several actions to guard (view, update, delete), a Policy keeps them together in one class. Generate one tied to a model:
php artisan make:policy PostPolicy --model=PostInside the policy, each method is one action. They receive the logged-in $user and the $post in question, and return true if it is allowed. Here, a user may update or delete a post only if they own it:
// app/Policies/PostPolicy.php
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}The rule $user->id === $post->user_id reads as "is the logged-in user the same person who owns this post?". If yes, the action is allowed; if no, it is blocked. You wrote the ownership rule once, in the obvious place.
You enforce a policy in the controller with $this->authorize():
// in the controller
public function update(Request $request, Post $post)
{
$this->authorize('update', $post); // blocks with 403 if not allowed
// ...update the post...
}$this->authorize('update', $post) runs the policy’s update method for the current user and this post. If it returns false, Laravel immediately stops with a 403 Forbidden response (403 is the standard code for "you are logged in, but not allowed"). If it returns true, your update code runs.
Note: Output:
Owner clicks "Edit" on their post → authorize passes, the post updates.
A different user tries the same URL → authorize fails → Laravel returns a 403 Forbidden page. The ownership rule is enforced in one place.
The decision flow for any guarded action:
- The user is authenticated — we know who they are.
- They try an action (e.g. update post 7).
- The controller calls
$this->authorize('update', $post)(or a@cancheck in Blade). - Laravel runs the matching Gate/Policy method, passing the user and the model.
- Return true → the action proceeds; return false → Laravel blocks it with a 403.
Tip: Rule of thumb: use a Gate for a quick app-wide check ("is admin?"), and a Policy when you have several rules about one model ("can view/update/delete this post"). Both power the same @can and authorize helpers.
Q. What does authorization (gates/policies) decide that authentication does not?
✍️ Practice
- Define a Gate and guard a link with
@canin Blade. - Generate a Policy so users can edit only their own records, and enforce it with
$this->authorize().
🏠 Homework
- Add a PostPolicy so only the author can edit or delete a post, and hide the edit/delete buttons from everyone else with
@can.