Multiple Authentication System using Native Laravel

victor steven
5 min readJun 16, 2018

--

Multiple authentication system is critical when an application grows to point when an administrator is needed to oversee the daily usage of such app. Am aware there are laravel packages that can help you achieve, lets see how this can be achieved using Native Laravel.

In this article am going to show you a step by step approach to actualize this.

Clone/download a new laravel framework and do the basic setup.

Go to your .env file, and reference the database that wish to use, preferably create a new database.

Run the following command in your terminal/cmd to setup basic authentication system that Laravel ships with:

php artisan make:auth

Then, create a Model, a Controller and a migration for the Admin.

  1. Admin.php, this is the Model
  2. AdminController.php, this is the Controller.
  3. yyyy_mm_dd_create_admins_table.php, this is the migration.

To create these three files in a single Laravel command, Run in the terminal:

php artisan make:model Admin -mc

where m repesents the migration file and c the controller to be created.

Next, populate the new migration file with the admin informations, something as simple as:

$table->increments('id');$table->string('name');$table->string('email')->unique();$table->string('password');

Remember this should be done in the up() function in the migration file.

Then run migration to migrate both the users migration file that ships with Laravel and the migration file you created using:

php artisan migrate

In this article we will consider a case where the Admin don’t need to register in the app, but only need to sign-in into the app. To achieve this, we need to seed the admins table. Create a new seeder by running:

php artisan make:seeder AdminTableSeeder 

Go to the database/seeds folder, you will see the seeder, populate it with values, this should be done inside the run() function, as an example:

Admin::create(['name' =>'Admin','email'=>'admin@app.com','password'=>bcrypt('password')]);

Remember to reference the Admin model in the seeder file, that is:

use App\Admin;

Next run the seeder in your terminal to seed the admins table:

php artisan db:seed --class=AdminTableSeeder

Next: we are going to create a custom middleware for the admin.

Go to config/auth.php in the file you will see:

'web' => ['driver' => 'session','provider' => 'users',],'api' => ['driver' => 'token','provider' => 'users',],

Write the following code in the next line:

'admin' => ['driver' => 'session','provider' => 'admins',],'admin-api' => ['driver' => 'token','provider' => 'admins',],

Scroll down the file, in the providers, you will see:

'users' => ['driver' => 'eloquent','model' => App\User::class,],

Add this right in the next line:

'admins' => ['driver' => 'eloquent','model' => App\Admin::class,],

Next go to the Admin model we created earlier and modify it as such:

<?phpnamespace App;use Illuminate\Notifications\Notifiable;use Illuminate\Foundation\Auth\User as Authenticatable;class Admin extends Authenticatable{use Notifiable;protected $table= "admins";protected $guard = 'admin';protected $fillable = ['name', 'email', 'password',];}

Next: go to the Admin controller we created earlier. create a constructor like this:

public function __construct(){$this->middleware('auth:admin');}

observe the ‘admin’ in the middleware.

Also create a function that will return the admin view (this is the admin dashboard):

public function index(){return view('admin');}

Create a view called admin.blade.php in resources/views

simply copy the contents in home.blade.php and paste in it.

Create a new file inside resources/views/auth called admin-login.blade.php

copy the contents in the login.php and paste in it. The only thing to change is the route name. Inside the admin-login.blade.php change the route name to:

action="{{ route('admin.login.submit') }}"

We need to create another controller for the login of the admin. run:

php artisan make:controller Auth/AdminLoginController

That command will save the controller in app/Http/Controllers/Auth

This should be the content of the controller:

<?phpnamespace App\Http\Controllers\Auth;use Illuminate\Http\Request;use App\Http\Controllers\Controller;use Auth;class AdminLoginController extends Controller{public function __construct(){$this->middleware('guest:admin', ['except'=>['logout']]);}public function showLoginForm(){return view('auth.admin-login');}public function login(Request $request){$this->validate($request, ['email' => 'required|email','password'=>'required|min:6',]);if (Auth::guard('admin')->attempt(['email'=>$request->email,'password'=>$request->password], $request->remember)){return redirect()->intended(route('admin.dashboard'));}return redirect()->back()->withInput($request->only('email', 'remember'));}public function logout(){Auth::guard('admin')->logout();return redirect('/');}}

Next, create a folder called components in resources/views, inside the folder, create a file called usage.blade.php, this file is both used by home.blade.php and admin.blade.php.

For instance, your admin.blade.php you created earlier will look like this:

@extends('layouts.app')@section('content')<div class="container"><div class="row justify-content-center"><div class="col-md-8"><div class="card"><div class="card-header">ADMIN Dashboard</div><div class="card-body">@if (session('status'))<div class="alert alert-success">{{ session('status') }}</div>@endif@component('components.usage')@endcomponent</div></div></div></div></div>@endsection

Your home.blade.php will also look the same except that the name in your card header will be Dashboard instead of Admin Dashboard.

When these are in place, the code inside the usage.blade.php created earlier should look like this:

@if(Auth::guard('web')->check())<p class="text-success">You are logged in as <strong>User</strong></p>@else<p class="text-danger">You are logged out as a <strong>User</strong></p>@endif@if(Auth::guard('admin')->check())<p class="text-success">You are logged in as <strong>Admin</strong></p>@else<p class="text-danger">You are logged out as a <strong>Admin</strong></p>@endif

Now, the body of your welcome.blade.php should look like this:

<body><div class="flex-center position-ref full-height">@if (Route::has('login'))<div class="top-right links">@auth<a href="{{ url('/home') }}">Home</a>@else<a href="{{ route('login') }}">Login</a><a href="{{ route('register') }}">Register</a>@endauth</div>@endif<div class="container"><div class="row"><div class="col-md-8 offset-md-2"><div class="card-body">@component('components.usage')@endcomponent</div></div></div></div></div></body>

Next, go to your web.php and add the routes mentioned thus far:

<?phpRoute::get('/', function () {return view('welcome');});Auth::routes();Route::get('/home', 'HomeController@index')->name('home');Route::get('/users/logout', 'Auth\LoginController@userlogout')->name('user.logout');
Route::prefix('admin')->group(function(){Route::get('/login', 'Auth\AdminLoginController@showLoginForm')->name('admin.login');Route::post('/login', 'Auth\AdminLoginController@login')->name('admin.login.submit');Route::get('/', 'AdminController@index')->name('admin.dashboard');Route::get('/logout', 'Auth\AdminLoginController@logout')->name('admin.logout');});

Pay close attention how we prefixed the admin routes with admin.

Next, we are going to rewrite the handle() function to use switch statement in app/Http/Middleware/RedirectIfAuthenticated.php, this will take the user to either the default dashboard or the admin dashboard, based on the login details provided.

public function handle($request, Closure $next, $guard = null){switch ($guard) {case 'admin':if(Auth::guard($guard)->check()){return redirect()->route('admin.dashboard');}break;default:if (Auth::guard($guard)->check()) {return redirect('/home');}break;}return $next($request);}

Then lastly, we are going to add a function app/Exceptions/Handler.php The function is called unauthenticated().

Note: This function already resides in vendor/laravel/framework/src/illuminate/Foundation/Exceptions/Handler.php

Copy the function to app/Exceptions/Handler.php and modify the content. This is what i mean:

protected function unauthenticated($request, AuthenticationException $exception){if($request->expectsJson()){return response()->json(['message' => 'Anauthorized Access'], 401);}$guard = array_get($exception->guards(), 0);switch ($guard){case 'admin':$login = 'admin.login';break;default:$login = 'login';break;}return redirect()->guest(route($login));}

Please also add the AuthenticationException class at the top of the file:

use Illuminate\Auth\AuthenticationException;

Now, test the application, as a normal user, start your server and navigate to:

localhost:8000/register, after successfull registration, it will taken to the users dashboard. log out and login in again, localhost:8000/login, you will also be taken to the users dashboard.

Now login in as an admin now, localhost:8000/admin/login with the details in the seeder. you will be taken to the admin dashboard.

Note: you must not logout as a user before before you will be able to login in as an admin and vice versa.

Laravel

Get the source code: https://github.com/victorsteven/Multiple-Authentication-System-using-Native-Laravel

--

--