using sessions
Then I suggest a regular web app.
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hello, I am making a multi auth api using laravel breeze api and snactum as a base this api should be consumed by a mobile application using tokens and a SPA with react using sessions
I have 3 guards Ex. student, teacher and admin
What is the right way to do it?
Here is how I managed to achieve it
Firstly I made 2 guards for every authenticatable table entity one for SPA using the session driver and one for the mobile with tokens using sanctum driver
My ./config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'web-api' => [
'driver' => 'sanctum',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'sanctum',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
Then I use the admin guard for my SPA only routes and admin-api for the token routes and I use both together if I want the routes to be authenticated from either SPA using sessions or Mobile using token same for the web and web-api guards
So the middlewares are auth:admin, auth:admin-api and auth:admin,admin-api same for the web
My ./routes/api-admin.php
<?php
use App\Http\Controllers\Admin\Auth\AuthenticatedTokenController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::prefix('v1/admin/')->name('api.v1.admin.')->group(function () {
// Auth Routes
Route::post('login', [AuthenticatedTokenController::class, 'store'])->name('mobile.login');
});
Route::middleware(['auth:admin,admin-api'])->prefix('v1/admin/')->name('api.v1.admin.')->group(function () {
// User Routes
Route::get('/user', function (Request $request) {
return Auth::user();
return [
'message' => 'admin page',
'admin' => $request->user()
];
});
});
// Auth Api Routes
Route::post('logout', [AuthenticatedTokenController::class, 'destroy'])->middleware('auth:admin-api')->name('mobile.logout');
Then I adjusted the guard in the sanctum config file to null ./config/sanctum.php
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => null,
Then I added the admin guards to the guest and auth middlewares to the SPA auth routes like guest:admin
And Lastly this is my AuthenticatedTokenController
<?php
namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
class AuthenticatedTokenController extends Controller
{
/**
* Handle an incoming authentication request.
*/
public function store(LoginRequest $request)
{
Auth::shouldUse('admin');
$request->validate([
'device_name' => 'required',
]);
$request->authenticate();
return $request->user()->createToken($request->device_name)->plainTextToken;
}
/**
* Destroy an authenticated session.
*/
public function destroy(Request $request): Response
{
$request->user()->currentAccessToken()->delete();
return response()->noContent();
}
}
Please or to participate in this conversation.