Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

drissboumlik's avatar

How to combine Laravel API (with Passport + Spatie permissions) and a web-based admin panel in the same app?

I’m currently building a Laravel application where the backend is a REST API. All my routes are defined in api.php, and I’m using Laravel Passport for API authentication along with Spatie Laravel Permissions for roles and permissions management.

Now, I’ve been asked to add an admin dashboard using Blade views — basically, a traditional web interface for internal users. I plan to define those routes in web.php.

My question is: 👉 How can I properly structure my application to support both API routes (authenticated via Passport) and web routes (using session/cookie authentication for the admin panel)?

Should I use a different guard for the web routes?

How do I handle authentication since Passport uses tokens but the web panel relies on sessions?

Any best practices for sharing user permissions (Spatie roles) between both sides?

Has anyone set up something similar — a Laravel app that serves as both an API and a web dashboard?

0 likes
3 replies
LaryAI's avatar
Level 58

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.php will use the web guard
  • API routes in routes/api.php will use the api guard

2. Authentication Separation

  • API:
    • Use Passport for API authentication (auth:api middleware).
    • Example:
      Route::middleware(['auth:api'])->get('/user', function (Request $request) {
          return $request->user();
      });
      
  • Admin Panel (Web):
    • Use Laravel’s inbuilt Auth scaffolding or Fortify/Breeze for login/registration routes.

    • Protect your admin routes using auth middleware (defaults to auth: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 web and api guards 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') or can: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.php and Blade/web routes in web.php.
  • CSRF: API routes are stateless and do not use CSRF, but web routes do.
  • Sessions: Only used in web guard/routes. API is stateless.
  • Middleware:
    • For web: ['web', 'auth', 'role:admin']
    • For API: ['api', 'auth:api', 'role:admin']

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 web guard for Blade/admin (session-based), api guard 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!

jlrdw's avatar

I’m currently building a Laravel application where the backend is a REST API. All my routes are defined in api.php, and I’m using Laravel Passport for API authentication along with Spatie Laravel Permissions for roles and permissions management.

Now, I’ve been asked to add an admin dashboard using Blade views — basically, a traditional web interface for internal users. I plan to define those routes in web.php.

This is fairly standard. For admins to login and do whatever is basically a regular web app. For the users or companies using the API it would be the stateless API. So users would get the JSON data returned.

My question is: 👉 How can I properly structure my application to support both API routes (authenticated via Passport) and web routes (using session/cookie authentication for the admin panel)?

With web routes for admin and API routes for the users of the API.

Also do you need an API? Probably 80 percent of the questions I see about API's, a regular mobile friendly app would be better suited. Just suggesting to check this.

Please or to participate in this conversation.