Langsung ke konten
KamusNgoding
Menengah Laravel 4 menit baca

Authentication di Laravel: Login, Register, dan Middleware

#laravel #authentication #login #register #breeze #middleware #auth #intermediate
📚

Baca dulu sebelum ini:

Pendahuluan

Task Manager yang kita bangun di artikel CRUD sebelumnya bisa diakses siapa saja — tidak ada sistem login. Di dunia nyata, tentu kamu ingin setiap user hanya bisa melihat dan mengelola task miliknya sendiri.

Inilah pentingnya Authentication — proses memverifikasi identitas pengguna. Di Laravel, ada dua cara mengimplementasikannya:

  1. Laravel Breeze — starter kit ringan, cocok untuk pemula (kita gunakan ini)
  2. Laravel Jetstream — starter kit lengkap dengan fitur tim, 2FA, API token
  3. Manual — membangun sendiri (untuk kasus khusus)

Di artikel ini kita akan:

  • Menginstall dan mengkonfigurasi Laravel Breeze
  • Memahami cara kerja sistem auth Laravel
  • Melindungi route dengan middleware auth
  • Mengaitkan task dengan user yang login
  • Menerapkan Authorization agar user hanya bisa akses datanya sendiri

Konsep Dasar: Authentication vs Authorization

Sering tertukar, padahal berbeda:

KonsepPertanyaanContoh
AuthenticationSiapa kamu?Login dengan email + password
AuthorizationApa yang boleh kamu lakukan?User A tidak boleh hapus task User B

Laravel menangani keduanya dengan elegan.


Install Laravel Breeze

# Install package Breeze
composer require laravel/breeze --dev

# Install scaffolding (pilih Blade + Alpine.js — paling sederhana)
php artisan breeze:install

# Pilih opsi:
# ┌ Which Breeze stack would you like to install? ──────────────────┐
# │ Blade with Alpine                                                 │
# └──────────────────────────────────────────────────────────────────┘
# → Pilih: blade (tekan Enter)

# Install dependensi Node.js dan build assets
npm install && npm run dev

# Jalankan migration (tambah kolom ke tabel users)
php artisan migrate

Breeze akan membuat:

  • Routes: /login, /register, /logout, /dashboard
  • Controllers: AuthenticatedSessionController, RegisteredUserController, dll
  • Views: auth/login.blade.php, auth/register.blade.php
  • Middleware konfigurasi

Menjelajahi File yang Dibuat Breeze

app/Http/Controllers/Auth/
├── AuthenticatedSessionController.php   ← Login & Logout
├── RegisteredUserController.php         ← Registrasi
├── PasswordResetLinkController.php      ← Lupa password
└── NewPasswordController.php            ← Reset password

resources/views/
├── auth/
│   ├── login.blade.php
│   ├── register.blade.php
│   └── forgot-password.blade.php
├── layouts/
│   ├── app.blade.php                    ← Layout untuk authenticated user
│   └── guest.blade.php                  ← Layout untuk tamu (login/register)
└── dashboard.blade.php                  ← Halaman setelah login

routes/auth.php                          ← Semua route auth

Cara Kerja Login Laravel

// app/Http/Controllers/Auth/AuthenticatedSessionController.php
// (Ini sudah dibuat otomatis oleh Breeze, tapi penting untuk dipahami)

public function store(LoginRequest $request): RedirectResponse
{
    $request->authenticate(); // Verifikasi credentials
    $request->session()->regenerate(); // Cegah session fixation attack
    return redirect()->intended(RouteServiceProvider::HOME);
}

Di balik layar:

  1. User submit form login (email + password)
  2. Auth::attempt(['email' => $email, 'password' => $password]) dipanggil
  3. Laravel mencari user dengan email tersebut
  4. Password di-hash dengan bcrypt dan dibandingkan
  5. Jika cocok: buat session, set user sebagai “logged in”
  6. Jika tidak cocok: kembalikan error

Middleware Auth — Melindungi Route

Setelah Breeze terpasang, melindungi route sangat mudah:

// routes/web.php

use App\Http\Controllers\TaskController;

// Rute yang membutuhkan login
Route::middleware('auth')->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');

    // Task hanya bisa diakses setelah login
    Route::resource('tasks', TaskController::class);
});

// Rute yang hanya boleh diakses tamu (belum login)
Route::middleware('guest')->group(function () {
    // Route login, register sudah ada di routes/auth.php
});

Jika user yang belum login mencoba akses /tasks, middleware akan otomatis redirect ke /login.


Helper Auth yang Sering Digunakan

// Mendapatkan user yang sedang login
$user = auth()->user();          // Mengembalikan User model
$user = Auth::user();            // Cara alternatif (facade)

// Mendapatkan ID user yang login
$userId = auth()->id();
$userId = auth()->user()->id;

// Cek apakah sudah login
if (auth()->check()) {
    // User sudah login
}

// Cek apakah belum login
if (auth()->guest()) {
    // User belum login
}

// Login manual (tanpa form)
Auth::login($user);
Auth::login($user, $remember = true); // Remember me

// Logout
Auth::logout();
request()->session()->invalidate();
request()->session()->regenerateToken();

// Di Blade
@auth
    <p>Halo, {{ auth()->user()->name }}!</p>
@endauth

@guest
    <a href="/login">Login</a>
@endguest

Mengaitkan Task dengan User

Sekarang kita perbarui Task Manager agar setiap task dimiliki oleh user tertentu.

Update Migration

// Jika menggunakan migrate:fresh (hati-hati: data hilang)
// Pastikan di migration tasks sudah ada:
$table->foreignId('user_id')->constrained()->onDelete('cascade');

Update Model Task

// app/Models/Task.php
protected $fillable = ['title', 'description', 'priority', 'is_done', 'due_date'];
// user_id SENGAJA tidak di $fillable — akan diisi dari auth()->id()

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

Update TaskController — Scope ke User Login

<?php
// app/Http/Controllers/TaskController.php

namespace App\Http\Controllers;

use App\Models\Task;
use App\Http\Requests\StoreTaskRequest;
use App\Http\Requests\UpdateTaskRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

class TaskController extends Controller
{
    // Hanya tampilkan task milik user yang login
    public function index(): View
    {
        $tasks = auth()->user()
                       ->tasks()
                       ->latest()
                       ->paginate(10);
        return view('tasks.index', compact('tasks'));
    }

    public function create(): View
    {
        return view('tasks.create');
    }

    // Simpan task dan set user_id otomatis
    public function store(StoreTaskRequest $request): RedirectResponse
    {
        auth()->user()->tasks()->create($request->validated());

        return redirect()->route('tasks.index')
                         ->with('success', 'Task berhasil ditambahkan!');
    }

    public function show(Task $task): View
    {
        // Pastikan hanya pemilik yang bisa lihat
        $this->authorize('view', $task);
        return view('tasks.show', compact('task'));
    }

    public function edit(Task $task): View
    {
        $this->authorize('update', $task);
        return view('tasks.edit', compact('task'));
    }

    public function update(UpdateTaskRequest $request, Task $task): RedirectResponse
    {
        $this->authorize('update', $task);
        $task->update($request->validated());

        return redirect()->route('tasks.index')
                         ->with('success', 'Task berhasil diperbarui!');
    }

    public function destroy(Task $task): RedirectResponse
    {
        $this->authorize('delete', $task);
        $task->delete();

        return redirect()->route('tasks.index')
                         ->with('success', 'Task berhasil dihapus!');
    }
}

Policy — Authorization yang Proper

Policy adalah cara terbaik untuk mengelola aturan authorization di Laravel.

# Buat Policy untuk Task
php artisan make:policy TaskPolicy --model=Task
<?php
// app/Policies/TaskPolicy.php

namespace App\Policies;

use App\Models\Task;
use App\Models\User;

class TaskPolicy
{
    // Apakah user boleh melihat task ini?
    public function view(User $user, Task $task): bool
    {
        return $user->id === $task->user_id;
    }

    // Apakah user boleh update task ini?
    public function update(User $user, Task $task): bool
    {
        return $user->id === $task->user_id;
    }

    // Apakah user boleh hapus task ini?
    public function delete(User $user, Task $task): bool
    {
        return $user->id === $task->user_id;
    }
}

Policy otomatis ter-register oleh Laravel jika menggunakan naming convention yang tepat (TaskPolicy untuk model Task).


Update View dengan Info User

{{-- resources/views/layouts/app.blade.php — tambahkan info user di nav --}}
<nav>
    <a href="{{ route('tasks.index') }}">📋 Task Manager</a>

    @auth
    <div style="display:flex; align-items:center; gap:16px;">
        <span>Halo, <strong>{{ auth()->user()->name }}</strong>!</span>
        <form action="{{ route('logout') }}" method="POST">
            @csrf
            <button type="submit" class="btn btn-secondary" style="font-size:0.85rem;">
                Logout
            </button>
        </form>
    </div>
    @endauth
</nav>

Redirect Setelah Login

Secara default, Laravel akan redirect ke /dashboard setelah login. Untuk mengubah ke /tasks:

// app/Http/Controllers/Auth/AuthenticatedSessionController.php
// (atau di RouteServiceProvider.php untuk Laravel 10)

// Di Laravel 11, ubah di routes/web.php atau gunakan intended():
return redirect()->intended(route('tasks.index'));

Atau lebih mudah, ubah konstanta HOME:

// app/Providers/RouteServiceProvider.php (Laravel 10)
public const HOME = '/tasks';

// Di Laravel 11, ubah di AuthenticatedSessionController:
return redirect()->intended(route('tasks.index'));

Troubleshooting: Error yang Sering Muncul

Setelah Login, Redirect ke Dashboard Bukan ke Halaman yang Dituju

Penyebab: Fungsi redirect()->intended() mengarah ke halaman yang coba diakses sebelum login. Jika langsung akses /login tanpa ada halaman tujuan, akan redirect ke HOME default.

Solusi:

// Ubah HOME di AuthenticatedSessionController
return redirect()->intended(route('tasks.index')); // Ganti dashboard dengan tasks.index

This action is unauthorized (403)

Penyebab: Policy mengembalikan false — user mencoba akses resource milik user lain.

Solusi:

// Periksa apakah task->user_id sama dengan auth()->id()
// Di TaskPolicy:
public function update(User $user, Task $task): bool
{
    return $user->id === $task->user_id; // Harus benar
}

CSRF Token Mismatch Setelah Session Expire

Penyebab: Session Laravel expire (default 120 menit), token CSRF di form sudah tidak valid.

Solusi:

// config/session.php — perpanjang lifetime
'lifetime' => 480,  // 8 jam (dalam menit)

// Atau tambahkan pesan yang lebih baik kepada user
// Di resources/views/errors/419.blade.php

Pertanyaan yang Sering Diajukan

Apa bedanya Laravel Breeze vs Jetstream?

Breeze adalah starter kit minimalis — hanya login, register, logout, dan reset password. Cocok untuk sebagian besar proyek dan lebih mudah dikustomisasi. Jetstream lebih lengkap dengan fitur tim (membagi akun), 2FA, manajemen API token, dan photo upload. Pilih Jetstream hanya jika kamu benar-benar butuh fitur tersebut.

Bagaimana cara implementasi “ingat saya” (remember me)?

Breeze sudah menyertakan checkbox “Remember me” di form login secara default. Di balik layar, Laravel akan menyimpan cookie remember token yang berlaku 400 hari. Tidak perlu kode tambahan!

Bagaimana cara tambah kolom ke tabel users?

php artisan make:migration add_phone_to_users_table --table=users
// Di migration baru:
$table->string('phone')->nullable()->after('email');
php artisan migrate

Lalu tambahkan 'phone' ke $fillable di Model User.

Apa itu email verification di Laravel?

Laravel bisa memaksa user memverifikasi email sebelum bisa akses halaman tertentu. Aktifkan dengan menambahkan MustVerifyEmail di Model User dan ->middleware('verified') di route. Breeze sudah menyiapkan semua view dan controller yang dibutuhkan.


Kesimpulan

Sistem autentikasi Task Manager kita sekarang sudah lengkap! Kita telah mengimplementasikan:

  • Laravel Breeze untuk login, register, dan logout yang siap pakai
  • Middleware auth untuk melindungi route dari akses tanpa login
  • User-scoped tasks — setiap user hanya bisa melihat tasknya sendiri
  • Policy untuk authorization yang bersih dan testable
  • @auth / @guest direktif di Blade untuk tampilan kondisional

Di artikel berikutnya, kita akan membangun REST API dengan Laravel Sanctum — mengekspos Task Manager sebagai API yang bisa dikonsumsi oleh aplikasi mobile atau frontend React/Vue.

Aplikasi kamu sekarang aman! Teruskan — kamu hampir menyelesaikan seluruh seri ini! 🔐

Artikel Terkait