Absolutely! Here’s how you can structure a Laravel application to serve both API requests (with Passport and Spatie Permissions) and a session-based web dashboard (admin panel using Blade):
1. Guards: Use Separate Guards for API and Web
- web guard: Handles traditional Laravel session/cookie-based login for your admin (Blade) dashboard.
- api guard: Handles API authentication via Passport (token-based).
Your config/auth.php should already look like this by default:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
- Web routes in
routes/web.phpwill use thewebguard - API routes in
routes/api.phpwill use theapiguard
2. Authentication Separation
- API:
- Use Passport for API authentication (
auth:apimiddleware). - Example:
Route::middleware(['auth:api'])->get('/user', function (Request $request) { return $request->user(); });
- Use Passport for API authentication (
- Admin Panel (Web):
-
Use Laravel’s inbuilt
Authscaffolding or Fortify/Breeze for login/registration routes. -
Protect your admin routes using
authmiddleware (defaults toauth:web).Route::middleware(['auth', 'role:admin'])->group(function () { Route::get('/admin', [AdminController::class, 'index']); });
-
3. Using Spatie Permissions Across Both Guards
By default, Spatie Laravel Permissions attaches to the User model (works fine unless you use polymorphic users).
- Both
webandapiguards use the same user provider and User model (App\Models\User). - You can assign/check roles and permissions on the user regardless of guard:
// Assign a role $user->assignRole('admin'); // works for both API and web // Check in controllers or middleware if ($user->hasPermissionTo('edit posts')) { // } - In API routes: Use
middleware('role:admin')orcan:permission-name. - In Web routes: Use same middleware for web guard; works the same.
Route::middleware(['role:admin'])->get('/admin', ...);
4. Best Practices
- Separation of Concerns: Keep your API-specific logic in
api.phpand Blade/web routes inweb.php. - CSRF: API routes are stateless and do not use CSRF, but web routes do.
- Sessions: Only used in
webguard/routes. API is stateless. - Middleware:
- For web:
['web', 'auth', 'role:admin'] - For API:
['api', 'auth:api', 'role:admin']
- For web:
5. Example Folder Structure
routes/
├── api.php // API endpoints, authenticated via Passport
└── web.php // Web dashboard routes, authenticated via sessions
Controllers:
- Place web controllers in
App\Http\Controllers - API controllers in
App\Http\Controllers\Api
6. Permissions/Role Sharing
No extra work is needed: permissions/roles are checked against the authenticated user, regardless of guard, because both use the same users table/model.
SUMMARY
- Use
webguard for Blade/admin (session-based),apiguard for API (Passport/tokens) - Spatie roles/permissions work across both
- Keep routes/controllers organized by interface
- No need to separate user tables/models unless absolutely necessary
References
Let me know if you want to see more specific examples or need help with any particular bit of setup!