Multi-authentication is a common requirement in modern web applications. In this tutorial, we will walk through setting up a Laravel project with multiple authentication guards — one for the default user, one for candidates, and one for employers. This guide is tailored for the freshersindian
project.
✅ What You’ll Learn
- Setting up Laravel
- Creating models, migrations, and guards
- Configuring
auth.php
- Middleware and route grouping
- Separate login forms and dashboards
- Custom authentication guards
- Adding auth protection
- Final testing and polish
🛠️ Step 1: Install Laravel
composer create-project laravel/laravel freshersindian
cd freshersindian
You’ll now have a fresh Laravel 11 or 12 application.
🔑 Step 2: Configure the Database
Open .env
and update your DB credentials:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=freshersindian
DB_USERNAME=root
DB_PASSWORD=
Run the migration to get the default users
table:
php artisan migrate
👥 Step 3: Create Models and Migrations for Candidates and Employers
php artisan make:model Candidate -m
php artisan make:model Employer -m
Update the migration files:
database/migrations/xxxx_create_candidates_table.php
public function up(): void
{
Schema::create('candidates', function (Blueprint $table) {
$table->id();
$table->string('full_name');
$table->string('email')->unique();
$table->string('password');
$table->string('country')->nullable();
$table->timestamps();
});
}
database/migrations/xxxx_create_employers_table.php
public function up(): void
{
Schema::create('employers', function (Blueprint $table) {
$table->id();
$table->string('company_name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
Run migrations:
php artisan migrate
🔒 Step 4: Update Models to Use Authenticatable
Make both models implement authentication:
app/Models/Candidate.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Candidate extends Authenticatable
{
use Notifiable;
protected $guard = 'candidate';
protected $fillable = ['full_name', 'email', 'password', 'country'];
protected $hidden = ['password'];
}
app/Models/Employer.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class Employer extends Authenticatable
{
use Notifiable;
protected $guard = 'employer';
protected $fillable = ['company_name', 'email', 'password'];
protected $hidden = ['password'];
}
⚙️ Step 5: Configure config/auth.php
Update guards
, providers
, and passwords
.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'candidate' => [
'driver' => 'session',
'provider' => 'candidates',
],
'employer' => [
'driver' => 'session',
'provider' => 'employers',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'candidates' => [
'driver' => 'eloquent',
'model' => App\Models\Candidate::class,
],
'employers' => [
'driver' => 'eloquent',
'model' => App\Models\Employer::class,
],
],
🌐 Step 6: Add Middleware to app/Http/Kernel.php
Add guards to route middleware:
protected $routeMiddleware = [
// ...
'auth.candidate' => \App\Http\Middleware\AuthenticateCandidate::class,
'auth.employer' => \App\Http\Middleware\AuthenticateEmployer::class,
];
Now let’s create the middleware files:
php artisan make:middleware AuthenticateCandidate
php artisan make:middleware AuthenticateEmployer
app/Http/Middleware/AuthenticateCandidate.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AuthenticateCandidate
{
public function handle($request, Closure $next)
{
if (!Auth::guard('candidate')->check()) {
return redirect('/candidate/login');
}
return $next($request);
}
}
app/Http/Middleware/AuthenticateEmployer.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AuthenticateEmployer
{
public function handle($request, Closure $next)
{
if (!Auth::guard('employer')->check()) {
return redirect('/employer/login');
}
return $next($request);
}
}
🧠 Step 7: Create Auth Controllers
php artisan make:controller CandidatesController
php artisan make:controller EmployersController
Example for CandidatesController
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CandidatesController extends Controller
{
public function loginForm()
{
return view('frontend.candidates.login');
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::guard('candidate')->attempt($credentials)) {
return redirect()->route('candidate.dashboard');
}
return back()->withErrors(['Invalid credentials']);
}
public function dashboardView()
{
$user = auth('candidate')->user();
return response()->json([
'message' => 'Candidate Dashboard',
'user' => $user,
]);
}
}
🛣️ Step 8: Define Routes
Separate the logic into files like routes/candidates.php
, routes/employers.php
, and include them in web.php
.
routes/web.php
require __DIR__.'/candidates.php';
require __DIR__.'/employers.php';
routes/candidates.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CandidatesController;
Route::get('/candidate/login', [CandidatesController::class, 'loginForm'])->name('candidate.login');
Route::post('/candidate/login', [CandidatesController::class, 'login'])->name('candidate.login.submit');
Route::middleware('auth.candidate')->group(function () {
Route::get('/candidate/dashboard', [CandidatesController::class, 'dashboardView'])->name('candidate.dashboard');
});
routes/employers.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\EmployersController;
Route::get('/employer/login', [EmployersController::class, 'loginForm'])->name('employer.login');
Route::post('/employer/login', [EmployersController::class, 'login'])->name('employer.login.submit');
Route::middleware('auth.employer')->group(function () {
Route::get('/employer/dashboard', [EmployersController::class, 'dashboardView'])->name('employer.dashboard');
});
🧪 Step 9: Testing It Out
You can use Laravel Tinker to manually create test users:
php artisan tinker
\App\Models\Candidate::create([
'full_name' => 'John Doe',
'email' => 'john@example.com',
'password' => bcrypt('password'),
'country' => 'India'
]);
\App\Models\Employer::create([
'company_name' => 'Tech Inc.',
'email' => 'employer@example.com',
'password' => bcrypt('password')
]);
Then navigate to:
/candidate/login
– Login as candidate/employer/login
– Login as employer/candidate/dashboard
– Protected candidate area/employer/dashboard
– Protected employer area
🧼 Bonus: Logout Methods
Add these to CandidatesController
and EmployersController
:
public function logout()
{
Auth::guard('candidate')->logout();
return redirect('/candidate/login');
}
public function logout()
{
Auth::guard('employer')->logout();
return redirect('/employer/login');
}
🧠 Recap
✅ What we did:
- Installed Laravel
- Created three auth systems: default user, candidate, employer
- Set up guards, providers, middleware, and dashboards
- Added proper routing and testing
- Fully separated login and session flow
✨ Final Thoughts
This setup is robust, scalable, and fully modular. You can now add more features like registration, password resets, profile editing, and dashboards using Blade or Vue.
📌 Make sure to secure routes, validate inputs, and follow best practices when deploying.