How to use Middleware for content restriction based on user role

Hello everyone, welcome back to justlaravel.com. Here in this post, I am going to show you how to use Middleware in your laravel applications to restrict content or some specific pages based on user role. This comes very handy when you have a simple paid membership site with where users who pay for a subscription can see pages which are not visible by other users. Or if you have admin, user, super admin type of roles, then also this Middleware in laravel works well.
Access Control is an important aspect of any application dealing with user-specific content. It provides with user’s ability to access specific applications components.
The official docs on this from laravel.com site here.
So let’s get started.
Working Demo Project on Github
Working Demo Video:
You can watch this video on YouTube here
Code Explanation Video:
You can watch this video on YouTube here
Setup User Roles
First I will create 3 user roles(admin, super admin, member) for testing our middleware functionality. I will create them by using laravel authentication scaffolding. So run the following command,
php artisan make:auth
Now we have login and registration setup, I will modify the registration script to add a new field “User Type”.
If you want to have a custom authentication – sigin/signup instead on this laravel scaffolding, I have made another post, you can look at them here.
First, add a new field to the user table, add this line $table->string('type');
to the user table create schema.
So locate the ###_create_users_table.php file at database\migrations
direcctory.
public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password'); $table->string('type'); $table->rememberToken(); $table->timestamps(); }); }
Now migrate the tables, run the following command,
php artisan migrate
Navigate to the registration blade file at, \resources\views\auth\register.blade.php
and below confirm password field and add a new select field as below,
<div class="form-group"> <label for="type" class="col-md-4 control-label" >User Type:</label> <div class="col-md-6"> <select class="form-control" name="type" id="type"> <option value="admin">Admin</option> <option value="super_admin">Super Admin</option> <option value="member">Member</option> </select> </div> </div>
Working Demo Project on Github
Now the registration form looks like,

Now I will modify the controller to save the user type field in the database. I will add 'type' => $data['type'],
to the create function at \app\Http\Controllers\Auth\RegisterController.php
Now the RegisterContoller’s create function will look like,
protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']), 'type' => $data['type'], ]); }
Also, I need to modify the model for users table. Add type
to the fillable array.
Go to \app\User.php
and modify the $fillable array
protected $fillable = [ 'name', 'email', 'password','type', ];
Now the application is all ready to register users with a specific role.
Middleware for specific roles
So now I will create a middleware for each of the user role. In the terminal or command prompt run the following command in the root of your app.
php artisan make:middleware AdminMiddleware
The above command creates a new AdminMiddleware.php
file at \app\Http\Middleware\
Similarly running the following commands, you can create middlewares for SuperAdmin and Member roles.
php artisan make:middleware SuperAdminMiddleware php artisan make:middleware MemberMiddleware
So open the AdminMiddleware.php
file, and there I keep a check on user type and if user type is not admin, will display a message that this content is restricted to the user type
Modify the handle()
function as below,
public function handle($request, Closure $next) { if ($request->user() && $request->user()->type != 'admin') { return new Response(view('unauthorized')->with('role', 'ADMIN')); } return $next($request); }
Similarly for SuperAdminMiddleware
,
public function handle($request, Closure $next) { if ($request->user() && $request->user()->type != 'super_admin') { return new Response(view('unauthorized')->with('role', 'SUPER ADMIN')); } return $next($request); }
and for MemberMiddleware
,
public function handle($request, Closure $next) { if ($request->user() && $request->user()->type != 'member') { return new Response(view('unauthorized')->with('role', 'MEMBER')); } return $next($request); }
Now all the middleware files are ready, let’s make some separate routes particular for each user type.
Working Demo Project on Github
So in \routes\web.php
file, I will group all the particular middleware routes.
Route::group(['middleware' => 'App\Http\Middleware\AdminMiddleware'], function() { Route::match(['get', 'post'], '/adminOnlyPage/', 'HomeController@admin'); });
In the above snippet, I grouped all the admin related routes. Actually, I have written only one route(/adminOnlyPage/
) but you can write as many routes as possible there.
Similarly for SuperAdmin,
Route::group(['middleware' => 'App\Http\Middleware\MemberMiddleware'], function() { Route::match(['get', 'post'], '/memberOnlyPage/', 'HomeController@member'); });
And for Member,
Route::group(['middleware' => 'App\Http\Middleware\SuperAdminMiddleware'], function() { Route::match(['get', 'post'], '/superAdminOnlyPage/', 'HomeController@super_admin'); });
Views and Controllers for Middleware
In the above route snippets, I have set up some methods in HomeController
. And in the middleware, I am passing an unauthorized
view page in the middleware file.
So in that view. I will display a simple message as below in the file \resources\views\unauthorized.blade.php
<div class="title m-b-md"> You cannot access this page! This is for only '{{$role}}'" </div>

Working Demo Project on Github
And in HomeController, I just return to a view for each user type link.
public function admin(Request $req){ return view('middleware')->withMessage("Admin"); } public function super_admin(Request $req){ return view('middleware')->withMessage("Super Admin"); } public function member(Request $req){ return view('middleware')->withMessage("Member"); }
The view for middleware
page.
<div class="title m-b-md"> {{ strtoupper($message)}} only page! </div>

And finally after login, I will show 3 links of all the user types irrespective of any user logged in.
In the file \resources\views\home.blade.php
<div class="panel panel-default"> <div class="panel-heading">Dashboard</div> <div class="panel-body"> You are logged in! as <strong>{{ strtoupper(Auth::user()->type) }}</strong> Admin Page: <a href="{{ url('/') }}/adminOnlyPage">{{ url('/') }}/adminOnlyPage</a> Super Admin Page: <a href="{{ url('/') }}/superAdminOnlyPage">{{ url('/') }}/super_adminOnlyPage</a> Member Page: <a href="{{ url('/') }}/memberOnlyPage">{{ url('/') }}/memberOnlyPage</a> </div> </div>

So when you click on any of the links above, if the logged in user has access to that page it shows the content or else a message shows that your are not authorized to access the page.
That is it about this application. Here I used a very generic example with only one route for each group to make it simple. You can extend this understanding to implement the way you want.
Why u can not control it with just one middleware?
Hi. Thank you for this exceptional tutorial, I’m learning Laravel right now and this tutorial is really precious!
But I’ve got an issue with the code you use in your middlewares. Let’s take AdminMiddleware.php: in the handle function you use this line of code:
return new Response(view(‘unauthorized’)->with(‘role’, ‘ADMIN’));
Well, this line raise the following error in my tests:
Undefined property: Illuminate\Auth\Access\Response::$headers
So I have replaced it, after a lot of search, with this one:
return response()->view(‘unauthorized’, [‘role’ => ‘ADMIN’, ‘logged’ => $request->user()->type]);
Now everything works like a charm but I’m not sure to understand why: as I said , I’m a novice and I still find the internal logic of Laravel a bit confusing 🙂
Cheers