How to run multi guard authentication in Laravel application.
cd /
mkdir www
cd www
composer create-project laravel/laravel wow.test
code wow.test
php artisan make:provider MultiGuardProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MultiGuardsProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
// Spatie multi guards admin guard and provider for Auth::guard('admin')->check();
$this->app->config["auth.guards.admin"] = [
'driver' => 'session',
'provider' => 'admins',
];
// Create Admin::class model first
$this->app->config["auth.providers.admins"] = [
'driver' => 'eloquent',
'model' => \App\Models\Admin::class,
];
}
}
# Only model, migrations, seeder, factory
php artisan make:model Admin -mfs
# All class for resources
php artisan make:model Admin -a
# Recreate
php artisan make:model Admin -a --force
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Contracts\Spatie\HasRolesPermissions;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasPermissions;
use Spatie\Permission\Traits\HasRoles;
class Admin extends Authenticatable
{
use HasFactory, Notifiable;
use HasRoles, HasPermissions;
use HasRolesPermissions;
/**
* Model table.
*/
protected $table = 'admins';
/**
* Auth guard.
*/
protected $guard = 'admin';
/**
* Append user relations (optional).
*/
protected $with = [];
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
protected function getDefaultGuardName(): string
{
return 'admin';
}
}
<?php
// User api
Route::prefix('web/api')->name('web.api')->middleware([
'web',
])->group(function () {
// Public routes
# Route::post('/login', [LoginController::class, 'index'])->name('login');
Route::post('/login', function () {
// Sample login
$credentials = request()->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::guard('web')->attempt($credentials)) {
request()->session()->regenerate();
return response()->json([
'message' => 'User logged',
'guard' => 'web',
]);
} else {
return response()->json([
'message' => 'User invalid credentials',
'guard' => 'web',
], 422);
}
});
// Private (guard web)
Route::middleware([
'auth:web',
])->group(function () {
Route::get('/logged', function () {
return response()->json([
'message' => 'User logged',
'guard' => 'web',
'id' => Auth::guard('web')->id(),
]);
});
});
});
// 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()->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',
])->group(function () {
Route::get('/logged', function () {
return response()->json([
'message' => 'Admin logged',
'guard' => 'admin',
'id' => Auth::guard('admin')->id(),
]);
});
});
});
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Auth;
use Tests\TestCase;
class MultiGuardsTest extends TestCase
{
/**
* Only logged users
*/
public function test_user_logged_error(): void
{
$response = $this->getJson('/web/api/logged');
$response->assertStatus(401)->assertJson([
'message' => 'Unauthenticated.',
]);
}
public function test_user_logged_success(): void
{
// Login user
$response = $this->postJson('/web/api/login', [
'email' => '[email protected]',
'password' => 'password',
]);
$response->assertStatus(200);
// User logged
$response = $this->getJson('/web/api/logged');
$response->assertStatus(200)->assertJson([
'message' => 'User logged',
'guard' => 'web',
]);
// Admin not logged
$response = $this->getJson('/web/api/admin/logged');
$response->assertStatus(401)->assertJson([
'message' => 'Unauthenticated.',
]);
}
/**
* Only logged admins
*/
public function test_admin_logged_error(): void
{
$response = $this->getJson('/web/api/admin/logged');
$response->assertStatus(401)->assertJson([
'message' => 'Unauthenticated.',
]);
}
public function test_admin_logged_success(): void
{
// Login admin
$response = $this->postJson('/web/api/admin/login', [
'email' => '[email protected]',
'password' => 'password',
]);
$response->assertStatus(200);
// Admin logged
$response = $this->getJson('/web/api/admin/logged');
$response->assertStatus(200)->assertJson([
'message' => 'Admin logged',
'guard' => 'admin',
]);
// User not logged
$response = $this->getJson('/web/api/logged');
$response->assertStatus(401)->assertJson([
'message' => 'Unauthenticated.',
]);
}
}
php artisan test --filter=MultiGuardsTest
// 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();
// Use User for request with guard in tests
$this->actingAs($user, 'admin');