Policies & Authorization — Laravel

Autentikasi (siapa kamu) vs Autorisasi (apa yang boleh kamu lakukan) adalah dua hal berbeda. Laravel punya 2 mekanisme utama untuk autorisasi: Gates (simple…

Autentikasi (siapa kamu) vs Autorisasi (apa yang boleh kamu lakukan) adalah dua hal berbeda. Laravel punya 2 mekanisme utama untuk autorisasi: Gates (simple closure-based) dan Policies (class untuk authorize operasi pada model).

Gates — Untuk Logic Global

Gunakan Gate untuk cek yang tidak terikat ke model tertentu. Definisikan di service provider.

// app/Providers/AppServiceProvider.php (atau AuthServiceProvider)
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define("view-admin-panel", function (User $user) {
        return $user->is_admin === true;
    });

    Gate::define("create-product", function (User $user) {
        return in_array($user->role, ["admin", "merchant"]);
    });
}

Di controller:

public function dashboard()
{
    if (! Gate::allows("view-admin-panel")) {
        abort(403);
    }
    // atau lempar exception otomatis:
    Gate::authorize("view-admin-panel");

    return view("admin.dashboard");
}

Policies — Untuk Authorize Operasi pada Model

Kalau kamu punya rule seperti "user hanya bisa edit/hapus post miliknya", gunakan Policy. Satu class per model, method per aksi.

php artisan make:policy PostPolicy --model=Post
// app/Policies/PostPolicy.php
namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    public function viewAny(User $user): bool
    {
        return true; // semua user bisa lihat list
    }

    public function view(User $user, Post $post): bool
    {
        return $post->is_published || $post->user_id === $user->id;
    }

    public function create(User $user): bool
    {
        return $user->email_verified_at !== null;
    }

    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->is_admin;
    }
}

Cara Pakai Policy

1. Di controller — authorize() method

class PostController
{
    public function update(Request $request, Post $post)
    {
        $this->authorize("update", $post);  // throw 403 kalau gagal

        $post->update($request->validated());
        return $post;
    }

    public function destroy(Post $post)
    {
        $this->authorize("delete", $post);
        $post->delete();
        return response()->noContent();
    }
}

2. Di route — ->can() middleware

Route::put("/posts/{post}", [PostController::class, "update"])
    ->middleware("can:update,post");

can:update,post otomatis cari PostPolicy, panggil update(), pass Auth::user() + Post dari route binding.

3. Di Blade — @can directive

@can("update", $post)
    <a href="{{ route("posts.edit", $post) }}">Edit</a>
@endcan

@cannot("delete", $post)
    <p>Kamu bukan pemilik post ini.</p>
@endcannot

4. Di API — $user->can() method

if ($request->user()->can("delete", $post)) {
    $post->delete();
}

Registering Policy

Laravel 11+ auto-discover policy kalau namanya standard (ModelModelPolicy di folder app/Policies/). Kalau tidak, daftar manual di AuthServiceProvider:

protected $policies = [
    Post::class => PostPolicy::class,
];

before() untuk Super-admin Bypass

Method before() dijalankan dulu sebelum method lainnya. Berguna untuk super-admin yang boleh apapun:

public function before(User $user, string $ability): ?bool
{
    if ($user->is_super_admin) {
        return true;  // boleh semua aksi
    }
    return null;  // lanjut ke method spesifik (view, update, dll)
}

Penting: return null kalau mau lanjut ke method spesifik. Return false akan langsung deny (sedikit berbeda semantik-nya).

Gate vs Policy — Kapan Pakai Apa?

Gate Policy
Scope Global / non-model Terikat ke model
Location Service provider closure Dedicated class
Reusability Sedang Tinggi
Contoh "view-admin-panel" "update Post, delete Post"

Rule of thumb: kalau rule-nya tentang "boleh tidak user X melakukan aksi Y pada model Z?", pakai Policy. Kalau sekadar "boleh tidak user X akses fitur Y?" (tanpa model), pakai Gate.

Checklist Authorization

Yang akan kamu pelajari