🏠 Home / Hub

🔐 Laravel 06 — Auth & Middleware

← Laravel Menu · ← Prev: CRUD

1. Authentication Concepts

TermMeaningExample
Authentication"ဘယ်သူလဲ" စစ်တာLogin with email + password
Authorization"ဘာလုပ်ခွင့်ရှိလဲ" စစ်တာOnly owner can edit their post
MiddlewareRequest interceptorRedirect to login if not authenticated
GuardAuth driverweb (session) vs api (token)
PolicyAuthorization logic per modelPostPolicy::update()
GateClosure-based authorizationGate::define('edit-post', ...)

2. Laravel Breeze (Quick Auth Scaffold)

# Install Breeze for ready-made login/register/password reset
composer require laravel/breeze --dev
php artisan breeze:install blade   # Blade + Tailwind
# or:
php artisan breeze:install vue     # with Vue/Inertia
php artisan breeze:install api     # API tokens only

npm install && npm run dev
php artisan migrate

# Gives you: Login, Register, Password Reset, Email Verify
# Routes in: routes/auth.php
# Views in:  resources/views/auth/

3. Manual Auth Controller

// app/Http/Controllers/Auth/LoginController.php
class LoginController extends Controller
{
    public function showLogin()
    {
        return view('auth.login');
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            'email'    => ['required', 'email'],
            'password' => ['required'],
        ]);

        if (Auth::attempt($credentials, $request->boolean('remember'))) {
            $request->session()->regenerate();         // prevent session fixation
            return redirect()->intended(route('dashboard'));
        }

        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ])->onlyInput('email');
    }

    public function logout(Request $request)
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect('/');
    }
}

4. Protect Routes with Middleware

// routes/web.php
// Option 1: Middleware on route group
Route::middleware('auth')->group(function () {
    Route::resource('posts', PostController::class);
    Route::get('/dashboard', [DashboardController::class, 'index'])
         ->name('dashboard');
});

// Option 2: Multiple middleware
Route::middleware(['auth', 'verified'])  // verified = email verified
     ->group(function () { /* ... */ });

// Option 3: Named middlewares
Route::middleware(['auth', 'role:admin'])->group(/* ... */);

// In controller constructor
class PostController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('auth')->only(['store', 'update', 'destroy']);
        $this->middleware('guest')->only(['create']);
    }
}

5. Auth Facade — Current User

use Illuminate\Support\Facades\Auth;

// Check login status
Auth::check()           // true if logged in
Auth::guest()           // true if NOT logged in

// Get current user
$user = Auth::user()    // User model instance (null if guest)
$id   = Auth::id()      // just the ID (null if guest)

// Helper functions (same thing)
$user = auth()->user()
$id   = auth()->id()

// In Blade templates
@auth
    <p>Welcome, {{ auth()->user()->name }}!</p>
    <a href="{{ route('logout') }}">Logout</a>
@endauth

@guest
    <a href="{{ route('login') }}">Login</a>
    <a href="{{ route('register') }}">Register</a>
@endguest

// Only show if user owns the post
@if(auth()->id() === $post->user_id)
    <a href="{{ route('posts.edit', $post) }}">Edit</a>
@endif

6. Policies — Authorization Per Model

# Generate a policy
php artisan make:policy PostPolicy --model=Post

// app/Policies/PostPolicy.php
class PostPolicy
{
    public function viewAny(User $user): bool
    {
        return true;                              // anyone can list posts
    }

    public function view(?User $user, Post $post): bool
    {
        return true;                              // ? = can be guest
    }

    public function create(User $user): bool
    {
        return true;                              // any logged-in user
    }

    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id       // only owner
            || $user->isAdmin();                  // or admin
    }

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

// Register in AuthServiceProvider (Laravel 10) or auto-discovered (11+)

// Use in controller
public function edit(Post $post)
{
    $this->authorize('update', $post);   // 403 if denied
    return view('posts.edit', compact('post'));
}

// Or with can()
if (auth()->user()->can('update', $post)) {
    // show edit button
}

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

@cannot('delete', $post)
    <p>(read-only)</p>
@endcannot

7. Custom Middleware

# Generate middleware
php artisan make:middleware EnsureUserIsAdmin

// app/Http/Middleware/EnsureUserIsAdmin.php
class EnsureUserIsAdmin
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!auth()->check() || !auth()->user()->is_admin) {
            abort(403, 'Admin access required');
        }

        return $next($request);   // pass request through
    }
}

// Register in bootstrap/app.php (Laravel 11+)
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'admin' => EnsureUserIsAdmin::class,
    ]);
})

// Use on routes
Route::middleware(['auth', 'admin'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index']);
});

8. Login Throttle (Rate Limiting)

// Laravel Breeze / built-in auth already includes throttle:6,1
// But for manual controllers, add to routes:

Route::post('/login', [LoginController::class, 'login'])
     ->middleware('throttle:10,1');   // 10 attempts per minute

// Or use RateLimiter in a service:
use Illuminate\Support\Facades\RateLimiter;

$key = 'login.' . Str::lower($email) . '|' . $request->ip();

if (RateLimiter::tooManyAttempts($key, 5)) {
    $seconds = RateLimiter::availableIn($key);
    return back()->withErrors([
        'email' => "Too many attempts. Try again in {$seconds}s."
    ]);
}

RateLimiter::hit($key, 60);    // record attempt, expire in 60s
// ... attempt auth ...
RateLimiter::clear($key);      // clear on success

📌 Study Checklist