Laravel 12 Multi-Auth System: Implementing Separate Admin and User Tables

Author

Kritim Yantra

Feb 28, 2025

Laravel 12 Multi-Auth System: Implementing Separate Admin and User Tables

In this blog post, we'll walk through creating a login system in Laravel 12 that supports both admin and user roles using separate database tables. This approach is useful when you need distinct authentication logic or different sets of permissions for admins and regular users. By the end, you'll have a fully functional login system with separate login forms and protected routes for each role.

Prerequisites

  • Laravel 12 installed on your system.
  • A basic understanding of PHP and Laravel concepts like models, controllers, and routes.
  • A database (e.g., MySQL) set up and configured in your Laravel project.

If you're new to Laravel, don’t worry—I’ll explain each step in detail.

Step 1: Set Up a New Laravel 12 Project

Create a new Laravel project using Composer:


composer create-project laravel/laravel blog-login-system "12.*"
    

Then navigate into your project directory:


cd blog-login-system
    

Step 2: Configure the Database

Create a new database in your MySQL server (e.g., blog_login_db). Then, update the .env file with your database credentials:


DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog_login_db
DB_USERNAME=root
DB_PASSWORD=
    

Replace root and the empty password with your actual database username and password.

Step 3: Create Models and Migrations for User and Admin

Laravel comes with a User model and migration by default. We’ll use this for regular users and create a separate Admin model and migration for admins.

3.1. Update the User Migration (if necessary)

The default users table migration is located in database/migrations/xxxx_xx_xx_xxxxxx_create_users_table.php. It should include fields like id, name, email, password, and timestamps.

3.2. Create the Admin Model and Migration

Run the following command to create the Admin model and its migration:


php artisan make:model Admin -m
    

This generates two files:

  • app/Models/Admin.php
  • database/migrations/xxxx_xx_xx_xxxxxx_create_admins_table.php

Update the admins migration to define the table structure:


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->string('password');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('admins');
    }
}
    

3.3. Run the Migrations

Run the migrations to create the users and admins tables:


php artisan migrate
    

Step 4: Set Up Authentication for Users

We’ll manually set up authentication for users using Laravel’s built-in features.

4.1. Create the User Login Controller

Create a LoginController for users in app/Http/Controllers/Auth/LoginController.php:


namespace App\Http\Controllers\Auth;

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

class LoginController extends Controller
{
    use AuthenticatesUsers;

    protected $redirectTo = '/home';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}
    

4.2. Create the User Login View

Create the login view for users at resources/views/auth/login.blade.php:


@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">{{ __('Login') }}</div>
                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf
                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
    

4.3. Define User Authentication Routes

In routes/web.php, add the following routes for user authentication:


use App\Http\Controllers\Auth\LoginController;

Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
Route::post('login', [LoginController::class, 'login']);
Route::post('logout', [LoginController::class, 'logout'])->name('logout');
    

Step 5: Set Up Authentication for Admins

To handle admin authentication separately, we’ll create a new guard and a login controller for admins.

5.1. Configure Authentication Guards

Open config/auth.php and update the guards and providers sections:


'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
],
    

5.2. Create the Admin Login Controller

Create app/Http/Controllers/Auth/AdminLoginController.php:


namespace App\Http\Controllers\Auth;

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

class AdminLoginController extends Controller
{
    use AuthenticatesUsers;

    protected $redirectTo = '/admin/dashboard';

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

    public function showLoginForm()
    {
        return view('auth.admin-login');
    }

    protected function guard()
    {
        return Auth::guard('admin');
    }

    public function logout(Request $request)
    {
        Auth::guard('admin')->logout();
        return redirect('/admin/login');
    }
}
    

5.3. Create the Admin Login View

Create resources/views/auth/admin-login.blade.php with a similar form to the user login:


@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 Login') }}</div>
                <div class="card-body">
                    <form method="POST" action="{{ route('admin.login') }}">
                        @csrf
                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
    

5.4. Define Admin Authentication Routes

Add the following routes in routes/web.php:


use App\Http\Controllers\Auth\AdminLoginController;

Route::get('admin/login', [AdminLoginController::class, 'showLoginForm'])->name('admin.login');
Route::post('admin/login', [AdminLoginController::class, 'login']);
Route::post('admin/logout', [AdminLoginController::class, 'logout'])->name('admin.logout');
    

Step 6: Create Protected Routes for Users and Admins

We’ll create simple dashboard views for both users and admins, protected by their respective authentication guards.

6.1. User Dashboard

Create app/Http/Controllers/HomeController.php:


namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    public function index()
    {
        return view('home');
    }
}
    

Create resources/views/home.blade.php:


@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Welcome, User!</h1>
    <form action="{{ route('logout') }}" method="POST">
        @csrf
        <button type="submit" class="btn btn-danger">Logout</button>
    </form>
</div>
@endsection
    

6.2. Admin Dashboard

Create app/Http/Controllers/AdminController.php:


namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AdminController extends Controller
{
    public function dashboard()
    {
        return view('admin.dashboard');
    }
}
    

Create resources/views/admin/dashboard.blade.php:


@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Welcome, Admin!</h1>
    <form action="{{ route('admin.logout') }}" method="POST">
        @csrf
        <button type="submit" class="btn btn-danger">Logout</button>
    </form>
</div>
@endsection
    

6.3. Protect Routes with Middleware

In routes/web.php, use middleware to protect the dashboards:


// User routes
Route::middleware(['auth'])->group(function () {
    Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
});

// Admin routes
Route::middleware(['auth:admin'])->group(function () {
    Route::get('/admin/dashboard', [App\Http\Controllers\AdminController::class, 'dashboard'])->name('admin.dashboard');
});
    

Step 7: Test the Login Systems

To test, you’ll need to create sample users and admins.

7.1. Create Sample Users and Admins

Use Laravel Tinker to add records:


php artisan tinker
    

Then run:


App\Models\User::create(['name' => 'User', 'email' => 'user@example.com', 'password' => bcrypt('password')]);
App\Models\Admin::create(['name' => 'Admin', 'email' => 'admin@example.com', 'password' => bcrypt('password')]);
    

7.2. Test User Login

Visit /login, enter user@example.com and password, and you should be redirected to /home.

7.3. Test Admin Login

Visit /admin/login, enter admin@example.com and password, and you should be redirected to /admin/dashboard.

7.4. Test Access Control

Try accessing /admin/dashboard without logging in as an admin; you should be redirected to /admin/login. Similarly, accessing /home without a user login should redirect to /login.

Conclusion

You’ve successfully set up a Laravel 12 application with separate login systems for admins and users using distinct database tables and authentication guards. This approach keeps the authentication logic clean and scalable for applications requiring role-based access.

Additional Tips

  • Customization: Add more fields to the users or admins tables (e.g., role, status) for finer control.
  • Middleware: For complex permissions, consider using middleware or packages like Spatie Laravel Permission.
  • Security: Always use hashed passwords (bcrypt) and validate user input to prevent security vulnerabilities.

If you have questions or encounter issues, feel free to leave a comment. Happy coding with Laravel!

Tags

Laravel Php

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Continue with Google

Related Posts