How to run multi guard authentication with permissions in Laravel application.
cd /
mkdir www
cd www
composer create-project laravel/laravel wow.test
code wow.testcomposer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan optimize:clear
php artisan migrate:fresh --seedphp artisan make:provider PermissionsProvider<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Spatie\Permission\Middleware\RoleMiddleware;
use Spatie\Permission\Middleware\PermissionMiddleware;
use Spatie\Permission\Middleware\RoleOrPermissionMiddleware;
class PermissionProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
// Spatie permissions
$this->app['router']->aliasMiddleware('role', RoleMiddleware::class);
$this->app['router']->aliasMiddleware('permission', PermissionMiddleware::class);
$this->app['router']->aliasMiddleware('role_or_permission', RoleOrPermissionMiddleware::class);
}
/**
* Bootstrap services.
*/
public function boot(): void
{
// Implicitly grant "Super Admin" role all permissions
// This works in the app by using gate-related
// functions like auth()->user->can() and @can()
Gate::before(function ($user, $ability) {
return $user->hasRole('super_admin') ? true : null;
});
}
}<?php
namespace App\Contracts\Spatie;
trait HasPermission
{
/**
* Append user all permissions (roles + direct)
*
* @var array
*/
protected $appends = ['permission'];
/**
* Spatie get all user permissions (direct + roles)
*/
public function getPermissionAttribute()
{
return $this->getAllPermissions();
}
/**
* Spatie roles with permissions (sample only)
*/
public function roles_permissions()
{
return $this->roles()->with(['permissions' => function ($q) {
$q->select('id', 'name', 'guard_name');
}]);
}
}use Spatie\Permission\Traits\HasRoles;
use App\Contracts\Spatie\HasPermission;
# The User, Admin model requires this trait
use HasRoles;
use HasPermission;
protected function getDefaultGuardName(): string { return 'web'; }Docs https://spatie.be/docs/laravel-permission/v6/basic-usage/basic-usage
// Get roles
$role = Role::findByName('user');
$role = Role::findByName('admin');
// Set roles, permissions
$role->givePermissionTo($permission);
$permission->assignRole($role);
// Create permissions
$permissions = [
'post_create',
'post_delete',
'post_update',
'post_show',
];
foreach ($permissions as $permission) {
// Admin guard
Permission::create([
'name' => $permission,
'guard_name' => 'admin',
]);
}
// Super Admin role
$superadmin = Role::create([
'name' => 'super_admin',
'guard_name' => 'admin'
]);
// Add permissions to super_admin role
$superadmin->givePermissionTo([
...$post,
]);
// Admin role
$admin = Role::create([
'name' => 'admin',
'guard_name' => 'web'
]);
// Add permissions to admin role
$admin->givePermissionTo([
...$post,
]);
// Writer role
$writer = Role::create([
'name' => 'writer',
'guard_name' => 'web'
]);
// Add permissions to writer role
$writer->givePermissionTo([
...$post,
]);
// User role (guard web)
$user = Role::create([
'name' => 'user',
'guard_name' => 'web'
]);
// Add permissions to role
$user->givePermissionTo([
...$post,
]); // User guard
$role = app(Role::class)->findOrCreate(RolesEnum::WRITER->value, 'web');
$role = Role::create(['guard_name' => 'web', 'name' => 'writer']);
// Admin guard
$role = app(Role::class)->findOrCreate(RolesEnum::WRITER->value, 'admin');
$role = Role::create(['guard_name' => 'admin', 'name' => 'writer']);
// Permissions
$direct_permission = app(Permission::class)->findOrCreate(PermissionsEnum::ARTICLE_DELETE->value, 'admin');
$direct_permission = Permission::create(['guard_name' => 'admin', 'name' => 'article_delete']);
// Add, find role
$user->assignRole('writer');
$role = Role::findByName('writer', 'web');
$role = Role::findByName('writer', 'admin');
// Roles
$user->assignRole(RolesEnum::WRITER);
$user->removeRole(RolesEnum::WRITER);
// Permissions
$role->givePermissionTo(PermissionsEnum::ARTICLE_VIEW);
$role->revokePermissionTo(PermissionsEnum::ARTICLE_VIEW);
// Roles
echo $user->hasRole('super_admin') ? 'YES' : 'NO';
echo $user->roles->pluck('name');
// Permissions from roles
echo $user->getPermissionsViaRoles()->pluck('name');
// Only direct permissions not from roles
$user->givePermissionsTo('article_update');
// Get
echo $user->permissions->pluck('name');
echo $user->getDirectPermissions()->pluck('name');
// Check
echo $user->can('edit_articles') ? 'Yes' : 'No';
echo $user->hasPermissionTo('edit_articles'); ? 'Yes' : 'No';
echo $user->hasAnyPermission(['edit_articles','delete_article']); ? 'Yes' : 'No';
echo $user->hasAllPermissions(['edit_articles','delete_article']); ? 'Yes' : 'No';
// Check permissions
$user->hasPermissionTo(PermissionsEnum::VIEWPOSTS->value);
// When calling Gate features, such as Model Policies, etc, prior to Laravel v11.23.0
$user->can(PermissionsEnum::VIEWPOSTS->value);// User routes
Route::prefix('web/api')->name('web.api')->middleware([
'web',
])->group(function () {
Route::get('/posts', function () {
return response()->json([
'message' => 'Display posts here',
'guard' => 'web',
]);
});
// Private (guard web)
Route::middleware([
'auth:web',
'role:writer,web'
])->group(function () {
// Only super_admin
});
});
// Admin api
Route::prefix('web/api/admin')->name('web.api.admin')->middleware([
'web',
])->group(function () {
// Public routes
# Route::post('/login', [AdminLoginController::class, 'index'])->name('login');
Route::post('/login', function () {
// Sample login
$credentials = request()->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::guard('admin')->attempt($credentials, request()->filled('remember'))) {
request()->session()->regenerate();
return response()->json([
'message' => 'Admin logged',
'guard' => 'admin',
]);
} else {
return response()->json([
'message' => 'Admin invalid credentials',
'guard' => 'admin',
], 422);
}
});
// Private (guard admin)
Route::middleware([
'auth:admin',
'role:super_admin,admin'
])->group(function () {
// Only super_admin
});
Route::middleware([
'auth:admin',
'role:super_admin|admin,admin'
])->group(function () {
// Only super_admin and admin
});
Route::middleware([
'auth:admin',
'role:super_admin|admin|writer,admin'
])->group(function () {
Route::get('/logged', function () {
return response()->json([
'message' => 'Admin logged',
'guard' => 'admin',
'id' => Auth::guard('admin')->id(),
]);
});
Route::get('/posts', function () {
return response()->json([
'message' => 'Display posts here',
'guard' => 'admin',
]);
});
// All routes
// Route::resource('/posts', PostController::class);
});
});# Shortcut to generate a model, migration, factory, seeder, policy, controller, and form requests for Route::resource
php artisan make:model Post --all --resource
# Then routes
Route::resource('/posts', PostController::class);
# Photo example
# php artisan make:controller PhotoController --model=Photo --resource --requests// Use User for request with guard
$this->actingAs($user, 'admin');
// Check is user logged with guard
Auth::guard('admin')->check();
// Logout user with guard
Auth::shouldUse('admin');
Auth::logout();
// Logout user with guard
Auth::guard('admin')->logout();php artisan cache:clear
php artisan test --filter=PermissionsTest