Hello there what's up guys! Today I'm going to show you how to make a multiple authentication app in Laravel using Jetstream. We are going to implement it so that you can have two routes: an admin and a normal user.
Let's say you are making an application, a website, or an e-commerce platform whereby you need to have an admin going to the inside, and also have the normal user directed to another part. This tutorial uses Laravel 8 and Jetstream to accomplish exactly that.
'll copy and paste some of the code in this tutorial because some of the code is lengthy, and just to save time to make this tutorial a bit smaller. But I will explain step by step so you just need to follow up with me and then you'll be good to go.
So enough of the talking, let's get started!
Step 1: Install Laravel & Jetstream
If you do not have it installed already, you just need to run this command:
laravel new multi-auth-app --jet
Choose your preferred stack (Livewire or Inertia). Once you finish, run npm install and npm run dev to compile your assets.
Step 2: Configure config/auth.php
The first thing we need to do is go to auth.php. It has the guards, which define the places where the user is taken when signed in. We are going to add an admin session guard, provider, and password broker so the admin can also get logged in.
// config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
// Add the admin guard here
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
// ...
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// Add the admins provider
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
// Add admin passwords broker
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
Step 3: Setting Up Admin Routes (routes/admin.php)
Under the routes/web.php, we are going to establish a new admin.php file requirement.
// routes/web.php
require __DIR__.'/admin.php';
Now, create routes/admin.php. Here we define the login controller routes and dashboard routes for our admin.
// routes/admin.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\LoginController;
Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
// Show Login form and authenticate
Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('/login', [LoginController::class, 'login'])->name('login.post');
// Admin Dashboard - Protected by Admin Middleware
Route::group(['middleware' => 'auth:admin'], function() {
Route::get('/dashboard', function () {
return view('admin.dashboard.index');
})->name('dashboard.index');
Route::post('/logout', [LoginController::class, 'logout'])->name('logout');
});
});
Step 4: The Login Controller
We're going to make an Admin folder under app/Http/Controllers and create a LoginController.php. This controller is going to handle all the login and logout functionality for our admins.
// app/Http/Controllers/Admin/LoginController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function __construct()
{
// Direct admins to the admin guard
$this->middleware('guest:admin', ['except' => ['logout']]);
}
public function showLoginForm()
{
return view('admin.auth.login');
}
public function login(Request $request)
{
// Validate the form
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6'
]);
// Attempt to log the admin in
if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->get('remember'))) {
// Redirect to their intended dashboard
return redirect()->intended('/admin/dashboard');
}
// Return back if unsuccessful
return back()->withInput($request->only('email', 'remember'));
}
public function logout(Request $request)
{
// Log out the admin
Auth::guard('admin')->logout();
return redirect('/admin/login');
}
}
Step 5: Handling Middleware & Exceptions
If the person is an admin, they should be taken to the admin dashboard. Let's update RedirectIfAuthenticated.php.
// app/Http/Middleware/RedirectIfAuthenticated.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
// Check using switch/if case. If admin, go to admin dashboard.
if ($guard === 'admin') {
return redirect()->route('admin.dashboard.index');
}
return redirect('/dashboard');
}
}
return $next($request);
}
}
Next, in app/Exceptions/Handler.php, we handle exceptions so that if the person is not an admin, they should not be taken to the normal user login page but rather back to the admin login.
// app/Exceptions/Handler.php
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Arr;
// Add this function inside your Handler class
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 401);
}
$guard = Arr::get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
Step 6: Admin Table Migration, Model, and Database Seeder
Now we need to create the admins table which defines for us what is in the admin (like password, email). Run:
php artisan make:migration create_admins_table
// database/migrations/xxxx_xx_xx_create_admins_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdminsTable extends Migration
{
public function up()
{
Schema::create('admins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('admins');
}
}
Create an Admin.php model manually in the app/Models directory to link up with our database authentication:
// app/Models/Admin.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Admin extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
Let's seed this table with dummy data so that whenever we log in, we already have some data to work with. Create an AdminsTableSeeder:
// database/seeders/AdminsTableSeeder.php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Admin;
use Illuminate\Support\Facades\Hash;
class AdminsTableSeeder extends Seeder
{
public function run()
{
Admin::create([
'name' => 'Admin',
'email' => 'admin@admin.com',
'password' => Hash::make('password'),
]);
}
}
Don't forget to call this inside your DatabaseSeeder.php using $this->call(AdminsTableSeeder::class);, and then migrate and seed your database!
Step 7: Views
To save time, you can literally replicate the normal user's login blade and change the POST route so it points to our newly created admin login logic. We are creating this at resources/views/admin/auth/login.blade.php.
<form method="POST" action="{{ route('admin.login.post') }}">
@csrf
<div>
<label for="email">Email</label>
<input id="email" type="email" name="email" required autofocus>
</div>
<div>
<label for="password">Password</label>
<input id="password" type="password" name="password" required>
</div>
<button type="submit">Log in</button>
</form>
And for our protected area, create resources/views/admin/dashboard/index.blade.php:
<div>
<h1>Admin Dashboard</h1>
<p>Lorem ipsum... Welcome to the Admin Panel.</p>
<form method="POST" action="{{ route('admin.logout') }}">
@csrf
<button type="submit">Logout</button>
</form>
</div>
Alright guys! So we have now successfully implemented the Laravel multiple authentication using Jetstream. What I would like you to go and do is that you can check any admin panel that you may want to use for the dashboard and plug it in.
If there's any question, just write it in the comment section below and I'll be sure to follow up with you. If you like this tutorial, just subscribe, share it with your friends, and let's meet in the next tutorial. Thank you for watching!
You can reference the full tutorial at: http://www.youtube.com/watch?v=Di993hgcs0M