Spatie Permissions can be integrated with Laravel Passport to manage and control API access through roles and permissions. Below is a detailed example and explanation of how to do this using both packages effectively in a Laravel application.
***
Prerequisites
- Have a Laravel application set up.
- Install and configure Laravel Passport for API authentication.
- Install Spatie Laravel Permissions package for role and permission management.
Step 1: Install and Configure Laravel Passport
Follow the official Laravel documentation to install Passport:
bash
composer require laravel/passport
php artisan migrate
php artisan passport:install
In `AuthServiceProvider`, include:
php
use Laravel\Passport\Passport;
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
Configure your `auth.php` to use the passport driver for the API guard:
php
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
***
Step 2: Install and Configure Spatie Permissions Package
Install the package using composer:
bash
composer require spatie/laravel-permission
Publish the configuration and migration files:
bash
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
Add the `HasRoles` trait to your User model:
php
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// other traits and properties
}
***
Step 3: Extending the Passport Client Model for Integration
Spatie's documentation suggests extending the Passport `Client` model to add the `HasRoles` trait, allowing clients to be associated with roles and permissions for client credentials grant use:
php
namespace App\Models;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Laravel\Passport\Client as BaseClient;
use Spatie\Permission\Traits\HasRoles;
class Client extends BaseClient implements AuthorizableContract
{
use HasRoles, Authorizable;
public $guard_name = 'api'; // matches the guard used by Passport for API
}
Then, in the `AuthServiceProvider` boot method, tell Passport to use the custom client model:
php
use Laravel\Passport\Passport;
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::useClientModel(\App\Models\Client::class);
}
***
Step 4: Update the Spatie Permission Configuration
In the `config/permission.php` file, set `use_passport_client_credentials` to `true` for proper Passport client credentials grant handling:
php
'use_passport_client_credentials' => true,
***
Step 5: Middleware and Route Protection Setup
Spatie Permissions provides middleware for roles and permissions. When using Passport, avoid wrapping routes with `auth:api` middleware for client credentials grant routes and instead use Spatie's middleware.
In `app/Http/Kernel.php`, the middleware alises for Spatie Permissions are:
php
protected $middlewareAliases = [
'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
];
You can protect routes like this:
php
Route::middleware(['client', 'permission:manage-users'])->group(function () {
Route::get('/admin/users', [UserController::class, 'index']);
});
Note: Use the `client` middleware for client credentials instead of `auth:api`.
***
Step 6: Assign Roles and Permissions
Create roles and permissions via seeders or in code:
php
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
Role::create(['name' => 'admin']);
Permission::create(['name' => 'manage users']);
$adminRole = Role::findByName('admin');
$adminRole->givePermissionTo('manage users');
Assign roles to users or clients:
php
$user = User::find(1);
$user->assignRole('admin');
$client = Client::find(1);
$client->assignRole('admin');
This ensures both users and OAuth clients have their permissions managed similarly.
***
Step 7: Using Permissions in API Requests
In controllers or middleware, check permissions:
php
if ($request->user()->can('manage users')) {
// Allow access
} else {
abort(403);
}
For client credentials grant, the client instance can also be checked for permissions as it has roles and permissions attached.
***
Step 8: Example Workflow
1. Client authenticates via Passport client credentials (`client_id` and `client_secret`).
2. The extended Passport Client model (with Spatie HasRoles trait) is used.
3. Middleware verifies the client's permissions according to roles assigned.
4. Access is granted or denied to protected endpoints based on permissions.
***
Additional Details
- The `guard_name` property or method on the Client model ensures correct guard identification.
- Middleware should not duplicate with `auth:api` on client credential routes.
- This integration effectively uses Spatie's permission system to secure both user and OAuth client authentication/authorization layers.
- Scopes in Passport can be managed alongside or replaced by Spatie Permissions for fine-grained access control.
- Role and permission syncing and revoking work the same for clients and users due to trait use.
***
Summary of Core Integration Points
- Extend Passport Client model with Spatie `HasRoles` trait and proper guard.
- Use custom Client model in Passport service provider.
- Set `use_passport_client_credentials` in Spatie config.
- Protect routes with Spatie middleware using client middleware.
- Assign roles and permissions to both users and clients.
- Use permission checks in routes or controllers.
***
This approach provides a seamless and powerful way to combine Laravel Passport's OAuth2 authentication with Spatie's robust role and permission management, enabling sophisticated API access control. The extended client model method especially enables permissions on OAuth clients themselves, which is useful for systems relying on client credentials grants or needing permission context on OAuth clients.
References:- Spatie Laravel Permission Docs: Passport Client Credentials Grant usage
- Spatie Basic Usage: Role and Permission assignment