Laravel Sanctum multiple guard/middleware

7.9k Views Asked by At

I am using Laravel Sanctum and Vuejs. I want to login as administrator and user separately, and of course their requests shouldn't reach each other.

I have user (model and controller) and admin (model and controller)

this is how i log in (both controller separately like this)

public function login(Request $request) {

$fields = $request->validate([
  'username' => 'required|string',
  'password' => 'required|string',
]);

$admin = Admin::where('username', $fields['username'])->first();

if (!$admin || !Hash::check($fields['password'], $admin['password'])) {
  return response([
    'error' => 'some error'
  ]);
}

$token = $admin->createToken($request['username'])->plainTextToken;

$response = [
  'admin' => $admin,
  'admin_token' => $token
];

return response($response, 201);
}

I can use like this

// routes/api.php
Route::group(['middleware' => ['auth:sanctum']], function() {
 //
});

but what I really want to use like this

// routes/api.php
Route::group(['middleware' => ['admin:sanctum']], function() {
 //
});

I tried

  // config/sanctum.php 
  'guard' => ['web', 'admin'],

and also I defined custom guard

// config/auth.php
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
           'driver' => 'session', // provider admin also defined and $table = 'admin' not admins
           'provider' => 'admin',
       ],
    ],

by the way when I tried to change driver like this driver => sanctum php artisan server:8000 dropped out.

2

There are 2 best solutions below

3
On

I encountered a similar problem while exploring Laravel 8 and Sanctum. I was able to make it work using Token Ability Middleware provided by Laravel Sanctum.

Here is how I think it can work for you.

In your controller, pass the role as ability while creating your token

public function login(Request $request) {

$fields = $request->validate([
  'username' => 'required|string',
  'password' => 'required|string',
]);

$admin = Admin::where('username', $fields['username'])->first();

if (!$admin || !Hash::check($fields['password'], $admin['password'])) {
  return response([
    'error' => 'some error'
  ]);
}

$token = $admin->createToken($request['username'], ['admin'])->plainTextToken;

$response = [
  'admin' => $admin,
  'admin_token' => $token
];

return response($response, 201);
}

Then you can use the Token Ability Middleware to identify the user role

// routes/api.php
Route::group(['middleware' => ['auth:sanctum','ability:admin']], function() {
 //
});

or

// routes/api.php
Route::group(['middleware' => ['auth:sanctum','abilities:admin']], function() {
 //
});

Similarly you can create ability for your User role.

Of course you will have to add the following to your $routeMiddleare in app/Http/Kernel.php for the above solution to work

'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,

You can learn more about this in official documentation Laravel Sanctum Token Abilities

1
On

Your problem is easaly solved with Laravel Spatie. Check this out https://spatie.be/docs/laravel-permission/v5/introduction. You can create roles & permissions and use CAN in your routes to distribute access along groups or single routes.