devnotes.

Authorization: Gates and Policies

Authentication answers 'who are you?'; authorization answers 'are you allowed to do this?'. Laravel offers two mechanisms: Gates (simple closures) and Policies (organized per-model classes).

Gates — good for quick, app-wide actions not tied to a specific model:

// In AppServiceProvider::boot()
Gate::define('access-admin-panel', function (User $user) {
    return $user->role === 'admin';
});

// Usage
if (Gate::allows('access-admin-panel')) { ... }

Policies — the recommended approach for model-specific authorization:

php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
    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 || $user->isAdmin();
    }
}

Usage in controllers, views, and Form Requests:

$this->authorize('update', $post);       // Throws 403 automatically if denied
@can('update', $post) <a>Edit</a> @endcan  // Blade
$user->can('delete', $post)                // Anywhere

Policies are auto-discovered by naming convention in modern Laravel versions, so there's usually no need to manually register them.

Laravel Authorization: Gates and Policies | DevNotes