Authentication Based on Roles

If you are working on a web application where you have to handle different types of user and redirect them to their secure page then we will cover this in this tutorial.

We will cover following scenarios in our app:

  • Our app consists of front end and back end
  • Front end for our site users and back end for our admins
  • We have a common login page where both user logs in
  • Using their role we will redirect them to front or back end

Create a user table

First of all we have to create a user table and a user model. To create a user table dynamically we have to create a migration file first.

Run following command in your terminal window while being on our root project folder:

php artisan make:migration user_table

Above command will generate a migration file in database/migrations folder now open this newly created file and modify it with following contents:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class UsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('password');
            $table->string('name')->index();
            $table->string('email')->unique()->index();
            $table->enum('role', ['user','admin'])->default('user');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

After we are done with above changes we have to run this migration which would create a new user table in our database. Make sure that your .env file is set with correct database credentials.

Now, open your terminal and run following command to create a user table:

php artisan migrate

Once user table is migrated correctly we need to modify our user model. Open app/User.php file and add following code to our model:

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    use Authenticatable, CanResetPassword;

    protected $table = 'users';

    protected $fillable = ['name', 'email', 'password', 'role'];

    protected $hidden = ['password', 'remember_token'];

    public function isAdmin() {
       return $this->role === 'admin';
    }

    public function isUser() {
       return $this->role === 'user';
    }
}

Understand laravel requests

In order to achieve our task first of all we need to understand how laravel process a web request:

  • user comes to a website using url
  • laravel finds url tied to a controller function using routes
  • then request goes through middlewares if defined any
  • then request goes to controller and process the view

So before a request actually goes to a controller it goes through middleware.

What is Laravel middleware?

Middleware is a layer between a user request and a controller. Basically, you can perform additional logics here before our request hits a controller.

For example, if you want certain users to see certain pages you can add that logic to middleware. This is exactly what we need for our app.

We want to make sure that user goes to front end while admins should go to admin pages. We want to prevent users to go to admin pages.

So we can basically create two middlewares here one for user and one for admins. In user middleware we want to make sure admins can not access user pages and for admin middleware we want to make sure users do not access.

Open your terminal window again by being in laravel project root directory and run following commands:

php artisan make:middleware UserAuthenticated
php artisan make:middleware AdminAuthenticated

This will generate two middlewares one for user and one for admin in app/Http/Middleware folder. Let's open up admin middle ware and make following changes:

namespace App\Http\Middleware;

use Auth;
use Closure;

class AdminAuthenticated
{
    public function handle($request, Closure $next)
    {
        if( Auth::check() )
        {
            // if user is not admin take him to his dashboard
            if ( Auth::user()->isUser() ) {
                 return redirect(route('user_dashboard'));
            }

            // allow admin to proceed with request
            else if ( Auth::user()->isAdmin() ) {
                 return $next($request);
            }
        }

        abort(404);  // for other user throw 404 error
    }
}

Basically we are checking to see if user is logged on if it does we check to see if user is not an admin then redirect them to their user dashboard or process the request.

This way even if user is logged on and tries to go to admin pages he will be redirected back to his dashboard and will not be able to access admin pages.

Let's add similar logic to our user middleware so that admins wont be able to access user pages and redirected back to their admin dashboard if they are logged on.

namespace App\Http\Middleware;

use Auth;
use Closure;

class UserAuthenticated
{
    public function handle($request, Closure $next)
    {
        if( Auth::check() )
        {
            // if user admin take him to his dashboard
            if ( Auth::user()->isAdmin() ) {
                 return redirect(route('admin_dashboard'));
            }

            // allow user to proceed with request
            else if ( Auth::user()->isUser() ) {
                 return $next($request);
            }
        }

        abort(404);  // for other user throw 404 error
    }
}

Activate our middlewares

Next, after we created our middlewares we need to activate them. By default laravel is not aware of our new middlewares so let's activate them.

Open app/Http/Kernel.php file and add following two lines:

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    // some other functions

    protected $routeMiddleware = [
        // some other middlewares
        'admin' => \App\Http\Middleware\AdminAuthenticated::class,
        'user'  => \App\Http\Middleware\UserAuthenticated::class
    ];
}

Adding middleware to routes

Now, that our middlewares are active they won't work automatically. When ever we create a new routes for user and admin we need to tell laravel that which routes should go to which middleware.

For example, all the user routes should user user middleware and all admin routes should user admin middleware along with web middleware.

Let's open routes/web.php file and add this middleware to appropriate routes.

// user protected routes
Route::group(['middleware' => ['auth', 'user'], 'prefix' => 'user'], function () {
    Route::get('/', 'HomeController@index')->name('user_dashboard');
});

// admin protected routes
Route::group(['middleware' => ['auth', 'admin'], 'prefix' => 'admin'], function () {
    Route::get('/', 'HomeController@index')->name('admin_dashboard');
});

Wow, lot of changes right however we want to make our app secure so anyways. The last change we have to make is in LoginController.

Now, that we have middlewares and we activated them its cool but when we login our app does not know where to redirect our user?

In login controller we have to redirect user based on their roles to their pages. Let's open LoginController and make following changes.

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    // some other functions go here

    protected function authenticated(Request $request, $user)
    {
        // to admin dashboard
        if($user->isAdmin()) {
            return redirect(route('admin_dashboard'));
        }

        // to user dashboard
        else if($user->isUser()) {
            return redirect(route('user_dashboard'));
        }

        abort(404);
    }
}

That is it. We have successfully secure our app based on user roles. Our app would follow the structure below:

  • user logs in to our app
  • LoginController will redirect user based on their role to either user or admin dashboard
  • our middleware will protect user crossing boundries
  • it wont let admin to see user pages and prevent users to see admin pages.

I hope you enjoyed this tutorial did you have any question feel free to ask and help me aware of things that I dont know about,