Authorization in Laravel
Gates and Policies control what users can do in your application. Gates define simple yes-or-no checks, while Policies group authorization logic around a specific model.
Defining Gates
Use Gate::define to register authorization checks. Gates are great for actions that don't belong to a specific model.
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->is_admin;
});
You can check a gate in controllers, views, or middleware.
if (Gate::allows('edit-settings')) {
// show settings page
}
Gate::authorize('edit-settings');
Creating Policy Classes
Policies organize authorization logic for a specific model. Generate a policy with artisan.
php artisan make:policy PostPolicy --model=Post
Each method in the policy corresponds to an action like viewAny, create, or update.
class PostPolicy
{
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
public function delete(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
Try it Yourself →
Using authorize()
Laravel automatically gates model actions when you register a policy. Use the authorize method in your controller to check permissions.
class PostController extends Controller
{
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
$post->update($request->validated());
return redirect('/posts');
}
}
If the check fails, Laravel returns a 403 response automatically.
Before and After Callbacks
You can run logic before or after any authorization check. This is useful for admin overrides or logging.
Gate::before(function (User $user, string $ability) {
if ($user->is_superadmin) {
return true;
}
});
Gate::after(function (User $user, string $ability, bool $result) {
if ($result) {
// log the authorization
}
});
The before callback can short-circuit the entire check. The after callback runs after all other gates and policies.