Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 10 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 25, 20264 min read

Implementing Middleware for API Security in Laravel

Learn to build custom middleware in Laravel to enforce resource ownership. Secure your API routes by verifying user access before controllers ever execute.

LaravelMiddlewareAPISecurityAuthorizationphpbackend

Previously in this course, we explored handling API validation and form requests to ensure incoming data integrity. While validation ensures the shape of your data is correct, it doesn't guarantee the user has the right to touch that data.

In a multi-user project board, it’s not enough to know that a project_id exists in the database. You must ensure the authenticated user actually owns that project. Relying on controllers to perform these checks leads to repetitive, error-prone code. Today, we’ll move this logic into custom middleware, enforcing security at the route level to keep our controllers lean and secure.

Why Middleware for Authorization?

Middleware provides a layer of "pre-flight" checks for your HTTP requests. By the time a request hits your controller, it should already be authenticated and authorized.

If you scatter ownership checks inside your controller methods, you violate the "Don't Repeat Yourself" (DRY) principle. If you decide to change how project ownership is calculated later, you'll have to hunt down every instance in your codebase. Middleware centralizes this logic, making your API more robust and easier to audit.

Creating the Ownership Middleware

We want to ensure that if a route contains a {project} parameter, the authenticated user is the owner of that project. Let's create a piece of middleware called EnsureProjectOwner.

Run the following Artisan command:

Bash
php artisan make:middleware EnsureProjectOwner

This creates app/Http/Middleware/EnsureProjectOwner.php. We will inject the Request object and use it to verify the relationship between the authenticated user and the project model bound to the route.

PHP
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureProjectOwner
{
    public function handle(Request $request, Closure $next): Response
    {
        #6A9955">// Get the project from the route parameters
        $project = $request->route('project');

        #6A9955">// Check if the user is authorized to access this project
        if ($project && $project->user_id !== $request->user()->id) {
            return response()->json([
                'message' => 'You do not have permission to access this project.'
            ], 403);
        }

        return $next($request);
    }
}

Registering and Applying the Middleware

To use this, you must register it in bootstrap/app.php (for Laravel 11+) or app/Http/Kernel.php (for older versions). In a modern Laravel application, you add it to your web or API middleware aliases:

PHP
#6A9955">// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'ensure.owner' => \App\Http\Middleware\EnsureProjectOwner::class,
    ]);
})

Now, apply it to your routes in routes/api.php:

PHP
Route::middleware(['auth:sanctum', 'ensure.owner'])->group(function () {
    Route::get('/projects/{project}', [ProjectController::class, 'show']);
    Route::put('/projects/{project}', [ProjectController::class, 'update']);
});

Handling Unauthorized Access

In the example above, we return a 403 Forbidden status code. This is the correct HTTP response for an authenticated user who is trying to access a resource they don't own.

Pro-tip: Never return a 404 Not Found for authorization failures unless you want to hide the existence of a resource entirely for security reasons (e.g., preventing ID enumeration). In most internal APIs, a 403 is much more helpful for debugging.

Hands-on Exercise

  1. Refactor: Take your existing ProjectController from the service-oriented task management lesson.
  2. Remove: Delete any manual if ($project->user_id !== auth()->id()) checks currently inside your controller methods.
  3. Apply: Wrap your project-related routes with the new ensure.owner middleware.
  4. Test: Create two users. Log in as User A and attempt to GET a project belonging to User B. Ensure you receive a 403 response.

Common Pitfalls

  • Missing Route Parameters: If your middleware expects a route parameter like {project} but you apply it to a route that doesn't have one, $request->route('project') will return null. Always check if the model exists before comparing IDs.
  • Order of Middleware: Middleware runs in the order defined in your route group. Always place auth:sanctum before ensure.owner. If you try to check ownership before the user is authenticated, $request->user() will be null, and your app will throw an exception.
  • Over-complicating Logic: Keep your middleware simple. If the authorization logic requires complex database queries or external service calls, consider using Laravel Policies instead. Middleware is best for simple, route-bound ownership checks.

Recap

We’ve successfully moved our authorization logic out of the controller and into a dedicated middleware layer. This keeps our controllers focused on handling requests and returning responses, rather than policing data access. We’ve enforced security by verifying project ownership, ensuring that users only interact with data that belongs to them.

Up next: We will discuss Database Transactions for Data Integrity, ensuring that our multi-step operations remain atomic and consistent even when things go wrong.

Previous lessonHandling API Validation and Form RequestsNext lesson Database Transactions for Data Integrity
Back to Blog

Similar Posts

LaravelJune 25, 20263 min read

Protecting Routes with Middleware: A Laravel Beginner’s Guide

Learn how to use Laravel middleware to secure your routes. We'll cover applying the auth middleware, protecting route groups, and managing redirects.

Read more
LaravelJune 26, 20263 min read

Task Manager: Deployment Preparation

Learn how to perform a final production audit for your Task Manager. We cover clearing secrets, verifying dependencies, and running final tests before launch.

Part of the course

Intermediate Laravel: Real-World Application Patterns

intermediate · Lesson 10 of 58

  1. 1

    Architecting for Maintainability

    3 min
  2. 2

    Implementing the Service Layer

    3 min
  3. 3

    Repository Pattern Fundamentals

    3 min
Read more
LaravelJune 25, 20263 min read

Preparing for Production: Laravel Optimization and Security

Learn to prepare your Laravel app for production. Master configuration caching, route optimization, and essential security settings to go live with confidence.

Read more
  • 4

    Project Board Domain Modeling

    3 min
  • 5

    Advanced Eloquent Scopes and Accessors

    4 min
  • 6

    Service-Oriented Task Management

    3 min
  • 7

    REST API Fundamentals with Sanctum

    3 min
  • 8

    Resource Controllers and API Responses

    3 min
  • 9

    Handling API Validation and Form Requests

    3 min
  • 10

    Implementing Middleware for API Security

    4 min
  • 11

    Database Transactions for Data Integrity

    3 min
  • 12

    Error Handling and Global Exceptions

    3 min
  • 13

    Introduction to Laravel Events and Listeners

    3 min
  • 14

    Asynchronous Processing with Queues

    4 min
  • 15

    Job Chaining and Batching

    Coming soon
  • 16

    Feature Testing Fundamentals

    Coming soon
  • 17

    Mocking Services and Repositories in Tests

    Coming soon
  • 18

    Testing Events and Jobs

    Coming soon
  • 19

    Database Factories and Seeding

    Coming soon
  • 20

    API Versioning Strategies

    Coming soon
  • 21

    Advanced Request Filtering and Sorting

    Coming soon
  • 22

    Handling File Uploads in REST APIs

    Coming soon
  • 23

    Real-time Notifications with Broadcasting

    Coming soon
  • 24

    Using Observers for Model Lifecycle Hooks

    Coming soon
  • 25

    Implementing Policies for Authorization

    Coming soon
  • 26

    Customizing Authentication Guards

    Coming soon
  • 27

    Rate Limiting API Endpoints

    Coming soon
  • 28

    Eloquent Performance Optimization

    Coming soon
  • 29

    Caching Strategies for Performance

    Coming soon
  • 30

    Using Traits for Code Reuse

    Coming soon
  • 31

    Advanced Dependency Injection with Service Providers

    Coming soon
  • 32

    Command Line Tools with Artisan

    Coming soon
  • 33

    Scheduled Tasks and Cron Jobs

    Coming soon
  • 34

    Integrating Third-Party Services

    Coming soon
  • 35

    Handling Webhooks

    Coming soon
  • 36

    Logging and Monitoring

    Coming soon
  • 37

    Database Migrations Best Practices

    Coming soon
  • 38

    Advanced Testing: Integration Tests

    Coming soon
  • 39

    Testing API Authentication

    Coming soon
  • 40

    Code Quality and Static Analysis

    Coming soon
  • 41

    Project Structure for Large Applications

    Coming soon
  • 42

    Environment and Configuration Management

    Coming soon
  • 43

    Deploying Laravel Applications

    Coming soon
  • 44

    Database Indexing Strategies

    Coming soon
  • 45

    Using Value Objects

    Coming soon
  • 46

    Strategy Pattern for Business Rules

    Coming soon
  • 47

    Advanced Queue Monitoring

    Coming soon
  • 48

    Building a Search API

    Coming soon
  • 49

    Handling Concurrency and Race Conditions

    Coming soon
  • 50

    API Documentation with OpenAPI

    Coming soon
  • 51

    Testing with Test Doubles

    Coming soon
  • 52

    Implementing Multi-Tenancy

    Coming soon
  • 53

    Refactoring Legacy Code

    Coming soon
  • 54

    Using Middleware for Feature Flags

    Coming soon
  • 55

    Building Reusable Packages

    Coming soon
  • 56

    Performance Profiling

    Coming soon
  • 57

    Secure API Design

    Coming soon
  • 58

    Event Sourcing Concepts

    Coming soon
  • View full course