Now, let's talk about Middleware and authentication. We created an administrator user, so let's assign access to that user to manage categories.
We have already seen the auth
Middleware, which allows only logged-in users to access Routes. The auth
is one of the Middlewares offered by the Laravel framework.
Middleware runs some checks before Routes, and if it returns false, it shows errors or redirect to some error page. For example, if someone wants to visit the /dashboard
URL, protected with auth
Middleware, they will automatically get redirected to the login page.
Laravel has some default Middlewares. You can always check them in the official documentation.
The web Middleware Group |
---|
Illuminate\Cookie\Middleware\EncryptCookies |
Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse |
Illuminate\Session\Middleware\StartSession |
Illuminate\View\Middleware\ShareErrorsFromSession |
Illuminate\Foundation\Http\Middleware\ValidateCsrfToken |
Illuminate\Routing\Middleware\SubstituteBindings |
We should assign our category resource route to the auth
Middleware. We could add the middleware()
method to the Route and provide the Middleware, or if the Route has multiple Middlewares, they can be provided as an array. But let's use Route group instead.
In the routes/web.php
, we already have one Route group for the profile links. We can move all the Routes to that group. The syntax to have grouped Routes is to use what you need on a Route
facade like middleware
, prefix
, etc., and then have a group
method with a closure and add all the Routes in the closure.
routes/web.php:
Route::get('/', function () { return view('welcome');}); Route::get('/dashboard', function () { return view('dashboard');})->middleware(['auth', 'verified'])->name('dashboard'); Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); Route::get('/dashboard', function () { return view('dashboard'); })->name('dashboard'); Route::resource('categories', \App\Http\Controllers\CategoryController::class); }); require __DIR__.'/auth.php'; Route::resource('categories', \App\Http\Controllers\CategoryController::class);
If you try to access any of these routes as a guest, you should be redirected to the login page.
Now, let's create our custom Middleware to check if a user is an admin. Middleware can be created using an artisan command.
php artisan make:middleware IsAdminMiddleware
Middlewares are created in the app/Http/Middleware
folder. The default structure of the Middleware is the handle()
, which returns the next request. Before the return, you can add conditions that your application needs and abort the next request if needed.
In our created Middleware, if the is_admin
field in the User
table is false, we must abort with the forbidden status. The currently authenticated user can be obtained using Laravel helpers auth()->user()
and then call the needed field.
app/Http/Middleware/IsAdminMiddleware.php:
class IsAdminMiddleware{ public function handle(Request $request, Closure $next): Response { if (! auth()->user()->is_admin) { abort(403); } return $next($request); }}
Next, we must register our Middleware to use it as an alias. Middleware is registered in the bootstrap/app.php
file.
bootstrap/app.php:
return Application::configure(basePath: dirname(__DIR__)) ->withProviders() ->withRouting( web: __DIR__.'/../routes/web.php', // api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', // channels: __DIR__.'/../routes/channels.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'is_admin' => \App\Http\Middleware\IsAdminMiddleware::class, ]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
Now, we can use is_admin
Middleware in our application. Because we need to restrict access only to category routes, Middleware needs to be used on that route instead of a group.
routes/web.php:
Route::get('/', function () { return view('welcome');}); Route::middleware('auth')->group(function () { // ... Route::resource('categories', \App\Http\Controllers\CategoryController::class)->middleware('is_admin'); }); require __DIR__.'/auth.php';
Another option to apply Middleware instead of using aliases pass the Middleware class.
routes/web.php:
Route::get('/', function () { return view('welcome');}); Route::middleware('auth')->group(function () { // ... Route::resource('categories', \App\Http\Controllers\CategoryController::class)->middleware(\App\Http\Middleware\IsAdminMiddleware::class); }); require __DIR__.'/auth.php';
If you try to access categories Routes with a user who isn't an admin, you will see a forbidden error message.
After add the middleware IsAdminMiddleware, then it show errors: Attempt to read property "is_admin" on null
is_admin
value cannot be null. It should be true (1) or false (0)Good evening, if I put the Part
if (! auth()->user()->is_admin) { abort(403); }
in the IsAdminMiddleware.php I get the error "undefined method user" . Do I have to add something in the "use" part at the top ?
But it works, just vs.code shows an error in the file.
vscode does not understand. maybe getting user from the request vscode wouldn't complain.
$request->user()
Oh this leads to a great Server Error. Anyhow its an Intelliphense Error (i saw it on google). Its not nice, because the whole strucutre is red in vs code is red and it shows an error. But the code works fine :-) So its ok for me I think.
But thanks a lot !
"If you try to access any of these routes as a guest, you should be redirected to the login page."
I can confirm this part. But I don't get where in the Laravel Framework code this bit is handle.
What if I want to redirect it to a different route, (probably not I good idea, but I just want to play around) how can I do that?
Thanks in advance.
This code is handled using
Middleware
. Specifically this one:vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php
And you can always change where it redirects:
https://laraveldaily.com/search?q=login%20redirect
Thanks @Modestas.