• Home
  • Blogs
  • Laravel 12 Custom Admin Authentication Login, Logout (Part 1)
Blog Details

Laravel 12 Custom Admin Authentication Login, Logout (Part 1)

Authentication is one of the most essential features of any web application. While Laravel provides built-in authentication for users, many web applications require separate admin authentication to protect the backend panel.

In this tutorial, you’ll learn how to create a custom admin authentication system in Laravel 12 using a separate admins table, custom guard, login system (by email or username), and helper functions — step-by-step from setup to login functionality.

This guide is perfect for developers who want to build a professional admin panel with secure and independent authentication logic.


๐Ÿงฉ What You’ll Learn

By the end of this tutorial, you’ll be able to:

  • Create an Admin Model and Migration

  • Configure a Custom Guard and Provider for Admins

  • Build an Admin Login Form

  • Create a Custom AuthController for Admin Login

  • Implement Login by Email or Username

  • Use a Helper Function for Authentication Redirects

  • Logout
  • Secure Your Admin Panel Routes


๐Ÿ›  Step 1: Create the Admin Model and Migration

First, run the following Artisan command to create your Admin model and its migration file:

php artisan make:model Admin -m

Now, open the migration file created under database/migrations and add the following schema:

  Schema::create('admins', function (Blueprint $table) {
            $table->id();
            $table->string('name', 100);
            $table->string('username', 100)->unique();
            $table->string('email', 150)->unique();
            $table->string('password');
            $table->string('phone', 20)->nullable();
            $table->string('image')->nullable();
            $table->enum('gender', ['male', 'female'])->nullable();
            $table->enum('status', ['active', 'inactive'])->default('inactive'); 
            $table->timestamps();
        });

Then run the migration:

php artisan migrate

This will create the admins table in your database with all necessary columns for authentication.


๐Ÿ‘จ‍๐Ÿ’ป Step 2: Define the Admin Model

Open app/Models/Admin.php and update it as follows:

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;

use Spatie\Permission\Traits\HasRoles;


class Admin extends Authenticatable
{
    use HasFactory, Notifiable, HasRoles;
    protected $guard = 'admin';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'username',
        'email',
        'phone',
        'password',
        'image',
        'status'
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}

Explanation:

  • Authenticatable is used instead of Model to enable Laravel’s built-in authentication features.

  • HasRoles is included from Spatie Permission Package (optional but useful for role-based permissions).

  • $guard = 'admin' tells Laravel to use the admin guard when authenticating this model.


โš™๏ธ Step 3: Configure Admin Guard and Provider

Now, let’s register a custom guard and provider for the admin in config/auth.php.

Find the guards and providers arrays and update them like this:

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


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => env('AUTH_MODEL', App\Models\User::class),
        ],

        'admins' => [
            'driver' => 'eloquent',
            'model' => env('AUTH_MODEL', App\Models\Admin::class),
        ],
    ],

Explanation:

  • The web guard handles normal user authentication.

  • The admin guard is a new guard that will manage admin logins separately using the admins table.


๐Ÿงญ Step 4: Create Admin Routes

In routes/web.php, define your admin routes:

Route::prefix('admin')->group(function () {
    Route::get('login', [AuthController::class, 'login'])->name('admin.login');
    Route::post('login/submit', [AuthController::class, 'login_submit'])->name('admin.login.submit')
});

Explanation:

We’re grouping admin routes under the /admin prefix to separate them from frontend routes.
You can later add routes like admin/dashboard, admin/logout, etc.


๐Ÿงพ Step 5: Create the Admin Login Form (Blade File)

Here’s a sample Blade template for your login form:

 
    <form method="post" action="{{ route('admin.login.submit') }}">
                            @csrf
                            <div class="form-group">
                                <div class="form-label-group">
                                    <label class="form-label" for="default-01">Email or Username*</label>
                                </div>
                                <div class="form-control-wrap">
                                    <input type="text"name="email_username" required id="email_username"
                                    value="{{ old('email_username') }}" class="form-control form-control-lg"placeholder="Enter your email address or username">
                                </div>
                                <div class="text-danger">
                                    @error('email_username')
                                        {{ $message }}
                                    @enderror
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="form-label-group">
                                    <label class="form-label" for="password">Password*</label>
                                    <a class="link link-primary link-sm" href="{{ route('admin.forgetpass') }}">Forgot password?</a>
                                </div>
                                <div class="form-control-wrap">
                                    <a href="#" class="form-icon form-icon-right passcode-switch lg" data-target="password">
                                        <em class="passcode-icon icon-show icon ni ni-eye"></em>
                                        <em class="passcode-icon icon-hide icon ni ni-eye-off"></em>
                                    </a>
                                    <input type="password"required name="password"
                                    id="password"  class="form-control form-control-lg" placeholder="Enter your passcode">
                                </div>
                                <div class="text-danger">
                                    @error('password')
                                        {{ $message }}
                                    @enderror
                                </div>
                            </div>
                            <div class="form-group">
                                <button class="btn btn-lg btn-primary btn-block">Sign in</button>
                            </div>
                        </form>

Tips:

  • You can use Bootstrap or a custom UI like DashLite for a modern admin panel.

  • Use @csrf for protection against CSRF attacks.


๐Ÿงฐ Step 6: Add Helper Function

Create a helper function in app/Helpers/helpers.php (make sure to autoload it via composer.json if not already done):

    function check_admin_auth($routeName)
    {
        if (Auth::guard('admin')->check()) {
            return redirect()->route('admin.dashboard');
        }
        return view($routeName);
    }

Purpose:
This helper checks if the admin is already logged in and redirects them to the dashboard if so.


๐Ÿง‘‍๐Ÿ’ผ Step 7: Create AuthController

Now create the controller:

php artisan make:controller Admin/AuthController

Then add the following logic:

namespace App\Http\Controllers\Admin;

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

class AuthController extends Controller
{
    public function login()
    {
        return check_admin_auth('adminpanel.auth.login');
    }

    public function login_submit(Request $request)
    {
        // Validate input
        $request->validate([
            'email_username' => 'required',
            'password' => 'required',
        ]);

        $credentials = $request->only('email_username', 'password');

        // Check if email or username and attempt login
        if (filter_var($credentials['email_username'], FILTER_VALIDATE_EMAIL)) {
            $authAttempt = Auth::guard('admin')->attempt([
                'email' => $credentials['email_username'],
                'password' => $credentials['password'],
                'status' => 'active'
            ]);
        } else {
            $authAttempt = Auth::guard('admin')->attempt([
                'username' => $credentials['email_username'],
                'password' => $credentials['password'],
                'status' => 'active'
            ]);
        }

        if ($authAttempt && Auth::guard('admin')->check()) {
            $user = Auth::guard('admin')->user();

            if (!in_array($user->status, ['inactive', 'suspended'])) {
                toastr()->success('Admin login successful.');
                return redirect()->intended(route('admin.dashboard'));
            }

            toastr()->error('Your account is inactive or suspended.');
            Auth::guard('admin')->logout();
            return redirect()->route('admin.login');
        }

        toastr()->error('Invalid credentials or account is inactive.');
        return redirect()->back();
    }
}

Explanation:

  • The controller validates inputs and authenticates using either email or username.

  • Uses Auth::guard('admin') to authenticate from the admins table.

  • Shows Toastr notifications for login success or failure.

  • Redirects inactive accounts back to the login page.

Step 8: Add Admin Logout Route

In your routes/web.php, inside the admin route group, add this line:

Route::middleware('auth:admin')->prefix('admin')->group(function () {
    Route::post('/logout', [AuthController::class, 'logout'])->name('admin.logout');
});

๐Ÿ”ธ The logout route must be a POST request for CSRF protection.

Add Logout Button (in Blade)

Here’s the improved and clean Blade code for your logout dropdown:

<div class="dropdown-inner">
    <ul class="link-list">
        <li>
            <a href="#"
               onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
                <em class="icon ni ni-signout"></em>
                <span>Sign out</span>
            </a>
        </li>
    </ul>

    <form id="logout-form" action="{{ route('admin.logout') }}" method="POST" style="display: none;">
        @csrf
    </form>
</div>

How it works:

  • When you click Sign out, it prevents the default link action.

  • Then, it submits the hidden form via POST to the admin.logout route.


Add the Logout Logic (Controller)

Your logout function looks great, just make sure it’s inside the same AuthController and under the correct namespace:

public function logout()
{
    Auth::guard('admin')->logout(); // โœ… ensures admin guard logout
    toastr()->success('Admin logged out successfully!');
    return redirect()->route('admin.login');
}

 


Step 8: Protect Admin Routes with Middleware

To restrict access to authenticated admins only, use middleware in routes:

Route::middleware('auth:admin')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('admin.dashboard');
});

This ensures only logged-in admins can access the dashboard.


โœ… Final Thoughts

Congratulations! ๐ŸŽ‰
You’ve successfully created a custom admin authentication system in Laravel 12 with a dedicated admins table, separate login, and authentication guard.

This setup helps you maintain a clean separation between user and admin logic, making your application secure, scalable, and professional.

Next Steps

  • Add Password Reset and Email Verification for admins.

  • Integrate Role & Permission using Spatie Laravel Permission.

Leave A Reply

Your email address will not be published. Required fields are marked

Ahmad

Ahmad Raza

Hi, I'm Ahmad Raza โ€” a passionate Web Developer and Laravel enthusiast.