Thomas
Thomas

Reputation: 131

Laravel Sanctum can be use Multiauth guard

I'm testing with laravel sanctum but here some issues.. I'm creating Admin guard.

enter image description here

When I change the middleware to auth:sanctum_admin.. it should be only can access by admin but here I can access with normal user account with web guard. I don't know why?...I used passport with multiauth package.it's fine. but here in sanctum can't be separate User Table and Admin.

Upvotes: 13

Views: 24470

Answers (8)

Dhairya Lakhera
Dhairya Lakhera

Reputation: 4808

Defining API sanctum guards using the sanctum driver

'guards' => [
        // Web Guards
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        //API Sanctum Guards
        'admin-api' => [
            'driver' => 'sanctum',
            'provider' => 'admins',
        ],
        'vendor-api' => [
            'driver' => 'sanctum',
            'provider' => 'vendors',
        ],
    ],

Defining Providers

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
    'vendors' => [
        'driver' => 'eloquent',
        'model' => App\Models\Vendor::class,
    ],
],

Generating Token

$user = Admin::where('email', $request->email)->first();
$token = $user->createToken(uniqid());
return ['token' => $token->plainTextToken];


$user = Vendor::where('email', $request->email)->first();
$token = $user->createToken(uniqid());
return ['token' => $token->plainTextToken];

Protecting Routes using sanctum guard

Route::middleware('auth:admin-api')->get('/admin', function (Request $request) {
    return $request->user();
});

Route::middleware('auth:vendor-api')->get('/vendor', function (Request $request) {
    return $request->user();
});

Upvotes: 1

edu.dev.ar
edu.dev.ar

Reputation: 81

In config/auth.php:

'guards' => [
    ...

    'api' => [
        'driver' => 'sanctum',
        'provider' => 'users',
    ],
],

(Tested in Laravel 9.x)

Upvotes: 1

Sanaulla
Sanaulla

Reputation: 1619

I also face the same issue and solved it by following -

  1. In auth.php add an extra Guard - front
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'front' => [
            'driver' => 'session',
            'provider' => 'members',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => Vanguard\User::class,
        ],

        'members' => [
             'driver' => 'eloquent',
             'model' => Vanguard\Member::class,
        ],
    ],
  1. Log in as a Default User or Member
/** Default Guard**/
if (Auth::attempt(['username' => $credentials['username'], 'password' => $credentials['password']], $request->get('remember'))) {
}
/** Front Guard **/
if (Auth::guard('front')->attempt(['username' => $credentials['username'], 'password' => $credentials['password']], $request->get('remember'))) {
}

  1. Finally add the Guard in sanctum.php
'guard' => ['front','web']

Upvotes: 0

Mohammad Bahmanyar
Mohammad Bahmanyar

Reputation: 19

  1. you must add your custom guard in config/auth.php.

'guards' => [

    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'custom-guard' => [
        'driver' => 'session',
        'provider' => 'custom-provider',
    ]
],

be careful, the driver in custom guard must be session. and set provider as:

'providers' => [
   'users' => [
       'driver' => 'eloquent',
       'model' => App\User::class,
   ],

   'custom-provider' => [
       'driver' => 'eloquent',
       'model' => App\CustomProvider::class,
   ],

], the App\CustomProvider::class must be the model. after that can easily use the guard in auth.

auth('custom-guard')->user()

Upvotes: 1

Balaji
Balaji

Reputation: 10937

config/auth.php

driver is sanctum

'guards' => [
    'users' => [
        'driver' => 'sanctum',
        'provider' => 'users',
    ],

    'partners' => [
        'driver' => 'sanctum',
        'provider' => 'partners',
    ],

    'admins' => [
        'driver' => 'sanctum',
        'provider' => 'admins',
    ],

        ],

provider:

providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],

    'partners' => [
        'driver' => 'eloquent',
        'model' => App\Models\Partner::class,
    ],

    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
],

model:

must be add Authenticatable

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class Admin extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Middleware:

Route::middleware(['auth:admin'])->get('/user', function(){
   
}

Guard:

auth()->guard('admin')->user();

Unauthenticated user message:

In app/Exceptions/Handler.php

use Illuminate\Auth\AuthenticationException;

function:

protected function unauthenticated($request, AuthenticationException $exception)
    {
       return response()->json(['message' => 'Unauthenticated.'], 401);

}

or

custom guard and custom redirect

public function render($request, Exception $exception)
{
    $class = get_class($exception);

    switch($class) {
        case 'Illuminate\Auth\AuthenticationException':
            $guard = array_get($exception->guards(), 0);
            switch ($guard) {
                case 'admin':
                    $login = 'admin.login';
                    break;
                default:
                    $login = 'login';
                    break;
            }

            return redirect()->route($login);
    }

    return parent::render($request, $exception);
}

Upvotes: 8

Harat
Harat

Reputation: 1366

@Abhishek Mitra

and for authorizatioin using Laravel Sanctum in case of Multiple Auth Guard, we can use middleware as such

Route::middleware(['auth:guard_name'])->get('/user', function(){
    return auth()->guard('guard_name')->user();
}

Upvotes: 8

Abhishek Mitra
Abhishek Mitra

Reputation: 135

You can, also use multiple guards in sanctum. To achieve this, follow these steps -

  1. Create your own guard as required. (In config/auth.php)
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],

        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ]
    ],
  1. Set providers. (In config/auth.php)
'providers' => [
       'users' => [
           'driver' => 'eloquent',
           'model' => App\User::class,
       ],

       'admins' => [
           'driver' => 'eloquent',
           'model' => App\Admin::class,
       ],
   ],
  1. Use this guard when you authenticate a user. (In route file)
    if(auth()->guard('admin')->attempt($request->only('email','password')))
    {
        return auth()->guard('admin')->user();
    }
    

Upvotes: 12

Nadir
Nadir

Reputation: 1

I think the default guard should be like this:

'defaults'{
    'guard' : "sanctum_admin",
    'passwords': 'admins',
}

Or

'defaults'{
    'guard' : 'web',
    'passwords' : 'users',
}

Upvotes: -1

Related Questions