Skip to content

Instantly share code, notes, and snippets.

@atomjoy
Last active April 29, 2025 09:29
Show Gist options
  • Save atomjoy/7804b9bfe221c9b097660b20f0003a62 to your computer and use it in GitHub Desktop.
Save atomjoy/7804b9bfe221c9b097660b20f0003a62 to your computer and use it in GitHub Desktop.
How to run multi guard authentication in Laravel application.

Laravel multiple guards

How to run multi guard authentication in Laravel application.

Cmd project

cd /
mkdir www
cd www

composer create-project laravel/laravel wow.test

code wow.test

Create provider

php artisan make:provider MultiGuardProvider

Guards provider

<?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,
        ];
    }
}

Create admin

# 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

Add default guard

<?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';
    }
}

Routes 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(),
            ]);
        });
    });
});

Tests

Guards test

<?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.',
        ]);
    }
}

Run test

php artisan test --filter=MultiGuardsTest

Auth user/admin with guard

// 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');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment