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

marcellopato's avatar

Filament and auth

I already had the entire admin part of my app with Laravel 10 when I met Filament and decided to use it because of the numerous possibilities. I don't see a problem with changing to the Filament admin route, but I noticed that any logged-in user can access this part, and I don't want that. I'm using a small script that I got from my colleague, the owner of the Laravel Daily portal, for roles and permissions, and it's working perfectly. How do I protect the Filament admin routes with this?

Let's see some code:

Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified',])->group(function () {
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->name('dashboard');

    // Superadministrators
    Route::group(['prefix' => '/admin'], function () {
        Route::resource('users', Super\UsersController::class);
        Route::resource('permissions', Super\PermissionController::class);
        Route::resource('roles', Super\RoleController::class);
        Route::resource('operators', OperatorController::class);
        Route::resource('products', ProductController::class);
        Route::resource('plans', PlanController::class);
        Route::resource('prices', PriceController::class);
        Route::post('/consulta-cnpj', [ReceitaWSController::class, 'consultaCNPJ']);
        Route::post('/conversor', [Super\ConverterController::class, 'convertData'])->name('converter');
    });

    //Managers
    Route::group(['prefix' => '/manager'], function (){
        Route::resource('agency', AgencyController::class);
        Route::post('/consulta-cnpj', [ReceitaWSController::class, 'consultaCNPJ']);

    });
});

The Middleware:

<?php

namespace App\Http\Middleware;

use App\Models\Super\Role;
use Closure;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Auth;

class AuthGates
{
    public function handle($request, Closure $next)
    {
        $user = Auth::user();

        if ($user) {
            $roles            = Role::with('permissions')->get();
            $permissionsArray = [];

            foreach ($roles as $role) {
                foreach ($role->permissions as $permissions) {
                    $permissionsArray[$permissions->title][] = $role->id;
                }
            }

            foreach ($permissionsArray as $name => $roles) {
                Gate::define($name, function ($user) use ($roles) {
                    return count(array_intersect($user->roles->pluck('id')->toArray(), $roles)) > 0;
                });
            }
        }

        return $next($request);
    }
}

And at Kernel.php

protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\AuthGates::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\AuthGates::class,
        ],
    ];

I would appreciate a well coded comment, if possible! Thanks!

0 likes
2 replies
LaryAI's avatar
Level 58

To protect the Filament admin routes with your existing roles and permissions system, you can utilize Laravel's authorization features, such as Gates or Policies, which you seem to be already setting up in your AuthGates middleware. Here's how you can modify your routes and middleware to ensure that only users with the appropriate permissions can access the Filament admin routes.

First, ensure that your AuthGates middleware is properly registered in the Kernel.php file, which you've already done.

Next, you'll want to define a specific Gate or set of Gates for accessing the Filament admin area. You might already have a permission like access_admin that you can check for.

Then, you can apply this Gate to your Filament routes using middleware. Here's an example of how you might modify your routes to include a permission check:

Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified', 'can:access_admin'])->group(function () {
    // Define your Filament admin routes here
    Route::get('/filament', function () {
        // Your Filament dashboard or another entry point
    })->name('filament.dashboard');
});

In the above code, 'can:access_admin' is a middleware that checks if the authenticated user has the access_admin permission. You'll need to replace access_admin with the actual permission name you use to control access to the admin area.

If you want to apply this check to all Filament routes, you can create a route group specifically for Filament and apply the middleware to that group.

Lastly, ensure that your AuthGates middleware is correctly setting up the Gates based on the user's roles and permissions. It looks like you're already doing this, but double-check that the permissions are correctly associated with the roles and that the user roles are being checked against these permissions.

Here's a simplified version of your AuthGates middleware that sets up the Gates:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;

class AuthGates
{
    public function handle($request, Closure $next)
    {
        $user = Auth::user();

        if ($user) {
            // Assuming you have a method to get all permissions associated with the user
            $userPermissions = $user->getAllPermissions();

            foreach ($userPermissions as $permission) {
                Gate::define($permission->name, function ($user) use ($permission) {
                    return $user->hasPermissionTo($permission->name);
                });
            }
        }

        return $next($request);
    }
}

Make sure to replace getAllPermissions and hasPermissionTo with the actual methods you use to retrieve permissions and check them against the user.

With these changes, your Filament admin routes should be protected, and only users with the correct permissions will be able to access them.

marcellopato's avatar

@LaryAI can you complete this route group pointing to filament default admin route?

Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified', 'can:access_admin'])->group(function () {
    // Define your Filament admin routes here
    Route::get('/filament', function () {
        // Your Filament dashboard or another entry point
    })->name('filament.dashboard');
});

Please or to participate in this conversation.