Shopping cart

    Subtotal $0.00

    View cartCheckout

    Protecting Laravel APIs with Sanctum & Implementing RBAC

    • Home
    • API
    • Protecting Laravel APIs with Sanctum & Implementing RBAC
    laravel_sanctum

    Introduction

    Laravel Sanctum provides a simple way to authenticate single-page applications (SPA), mobile applications, and simple API token authentication. However, to ensure robust security, combining Sanctum with Role-Based Access Control (RBAC) is essential. This approach allows you to enforce fine-grained access control on your API endpoints.

    In this guide, we’ll cover:

    • Installing and configuring Laravel Sanctum
    • Authenticating users with API tokens
    • Implementing Role-Based Access Control (RBAC)
    • Creating an example API with Car as the resource

    Step 1: Install and Configure Laravel Sanctum

    To begin, install Laravel Sanctum via Composer:

    composer require laravel/sanctum

    Next, publish the Sanctum configuration file:

    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

    Then, run migrations to create the necessary database tables:

    php artisan migrate

    After that, add the Sanctum middleware to app/Http/Kernel.php in the api middleware group:

    use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
    
    protected $middlewareGroups = [
        'api' => [
            EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    Step 2: Configure API Token Authentication

    In config/auth.php, update the guards to use Sanctum:

    'guards' => [
        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
        ],
    ],

    Now, modify the User model to include the HasApiTokens trait:

    use Laravel\Sanctum\HasApiTokens;
    
    class User extends Authenticatable
    {
        use HasApiTokens, Notifiable;
    }

    Authentication Routes

    Create routes for user authentication in routes/api.php:

    use App\Models\User;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Hash;
    use Illuminate\Support\Facades\Route;
    
    Route::post('/login', function (Request $request) {
        $user = User::where('email', $request->email)->first();
    
        if (! $user || ! Hash::check($request->password, $user->password)) {
            return response(['message' => 'Invalid credentials'], 401);
        }
    
        return ['token' => $user->createToken('api-token')->plainTextToken];
    });

    Step 3: Implement Role-Based Access Control (RBAC)

    Create the Role and Permission Models

    First, generate models and migrations for Role and Permission:

    php artisan make:model Role -m
    php artisan make:model Permission -m

    Next, update the migrations to define relationships:

    // database/migrations/xxxx_xx_xx_create_roles_table.php
    Schema::create('roles', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();
        $table->timestamps();
    });
    // database/migrations/xxxx_xx_xx_create_permissions_table.php
    Schema::create('permissions', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();
        $table->timestamps();
    });

    Define Relationships

    In User.php, add role and permission relationships:

    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
    
    public function hasRole($role)
    {
        return $this->roles->contains('name', $role);
    }

    Assign Middleware for Authorization

    Now, create a custom middleware RoleMiddleware:

    php artisan make:middleware RoleMiddleware

    Modify the middleware:

    use Closure;
    use Illuminate\Http\Request;
    
    class RoleMiddleware
    {
        public function handle(Request $request, Closure $next, $role)
        {
            if (! $request->user() || ! $request->user()->hasRole($role)) {
                return response(['message' => 'Forbidden'], 403);
            }
    
            return $next($request);
        }
    }

    Then, register middleware in app/Http/Kernel.php:

    protected $routeMiddleware = [
        'role' => \App\Http\Middleware\RoleMiddleware::class,
    ];

    Step 4: Create API for Cars with Role-Based Access

    Generate Model and Controller

    php artisan make:model Car -m
    php artisan make:controller CarController --api

    Define Routes

    In routes/api.php:

    use App\Http\Controllers\CarController;
    
    Route::middleware(['auth:sanctum', 'role:admin'])->group(function () {
        Route::post('/cars', [CarController::class, 'store']);
        Route::put('/cars/{car}', [CarController::class, 'update']);
        Route::delete('/cars/{car}', [CarController::class, 'destroy']);
    });
    
    Route::get('/cars', [CarController::class, 'index']);
    Route::get('/cars/{car}', [CarController::class, 'show']);

    Conclusion

    To summarize, using Laravel Sanctum for authentication and RBAC for authorization ensures that only authorized users can access and modify API resources. This approach not only provides security but also enhances flexibility in managing user roles.

    For expert assistance in securing your Laravel APIs, check out Techliphant!

    References

    Leave A Comment

    Your email address will not be published. Required fields are marked *