Separate Admin and User Login & Registration in Laravel 12 (2026) — Beginner-Friendly, Step by Step

Author

Kritim Yantra

Jan 08, 2026

Separate Admin and User Login & Registration in Laravel 12 (2026) — Beginner-Friendly, Step by Step

If you’ve ever built your first Laravel app, you probably started with this thought:

“I’ll just add login first… I’ll worry about admin later.”

Fast forward a few days, and suddenly:

  • Admins can access user pages
  • Users accidentally see admin URLs
  • Both use the same login form
  • And everything feels messy

I’ve been there. I learned this the hard way.

In this guide, we’ll build separate login and registration systems for Admins and Normal Users in Laravel 12, using:

  • Separate Blade files
  • Separate routes
  • Separate controllers
  • A clean, beginner-friendly model structure

No confusion. No hacks. Just clean Laravel.


What We’re Building (Clear Picture First)

By the end, you’ll have:

  • /login & /registerNormal users
  • /admin/login & /admin/registerAdmins
  • Separate views (Blade files)
  • Separate controllers
  • One shared User model (simple and practical)

Real-world analogy

Think of it like a building:

  • Visitors enter from the front desk
  • Staff/Admins enter from a secure back door
    Different doors, same building.

Step 1: Decide the Data Structure (Important)

We’ll use one users table, with a role field.

Why not two tables?

For beginners:

  • One table = simpler
  • Easier relationships
  • Less duplication

users table example

Schema::create('users', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->string('role')->default('user'); // user | admin
    $table->timestamps();
});

Rule

  • role = user → normal user
  • role = admin → admin

Step 2: User Model (Simple and Clean)

app/Models/User.php

class User extends Authenticatable
{
    protected $fillable = [
        'name',
        'email',
        'password',
        'role',
    ];

    protected $hidden = [
        'password',
    ];

    public function isAdmin()
    {
        return $this->role === 'admin';
    }
}

This small helper method will save you time later.


Step 3: Routes (Laravel 12 Style)

All routes go in routes/web.php.

User Routes

use App\Http\Controllers\Auth\UserAuthController;

Route::get('/register', [UserAuthController::class, 'showRegister']);
Route::post('/register', [UserAuthController::class, 'register']);

Route::get('/login', [UserAuthController::class, 'showLogin']);
Route::post('/login', [UserAuthController::class, 'login']);

Admin Routes

use App\Http\Controllers\Auth\AdminAuthController;

Route::prefix('admin')->group(function () {

    Route::get('/register', [AdminAuthController::class, 'showRegister']);
    Route::post('/register', [AdminAuthController::class, 'register']);

    Route::get('/login', [AdminAuthController::class, 'showLogin']);
    Route::post('/login', [AdminAuthController::class, 'login']);

});

Why prefixes matter

They clearly separate:

  • /login → users
  • /admin/login → admins

Less confusion. Better security.


Step 4: Controllers (Separated Logic)

Create Controllers

php artisan make:controller Auth/UserAuthController
php artisan make:controller Auth/AdminAuthController

UserAuthController

class UserAuthController extends Controller
{
    public function showRegister()
    {
        return view('auth.user.register');
    }

    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6',
        ]);

        User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
            'role' => 'user',
        ]);

        return redirect('/login');
    }

    public function showLogin()
    {
        return view('auth.user.login');
    }

    public function login(Request $request)
    {
        if (auth()->attempt($request->only('email', 'password'))) {
            return redirect('/dashboard');
        }

        return back()->withErrors(['email' => 'Invalid credentials']);
    }
}

AdminAuthController

class AdminAuthController extends Controller
{
    public function showRegister()
    {
        return view('auth.admin.register');
    }

    public function register(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6',
        ]);

        User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
            'role' => 'admin',
        ]);

        return redirect('/admin/login');
    }

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

    public function login(Request $request)
    {
        if (
            auth()->attempt($request->only('email', 'password')) &&
            auth()->user()->isAdmin()
        ) {
            return redirect('/admin/dashboard');
        }

        auth()->logout();
        return back()->withErrors(['email' => 'Admin access only']);
    }
}

Step 5: Blade Files (Separated Views)

Folder Structure

resources/views/auth/
├── admin/
│   ├── login.blade.php
│   └── register.blade.php
└── user/
    ├── login.blade.php
    └── register.blade.php

Example: auth/user/login.blade.php

<form method="POST" action="/login">
    @csrf
    <input type="email" name="email" placeholder="Email">
    <input type="password" name="password" placeholder="Password">
    <button>Login</button>
</form>

Example: auth/admin/login.blade.php

<form method="POST" action="/admin/login">
    @csrf
    <input type="email" name="email" placeholder="Admin Email">
    <input type="password" name="password" placeholder="Password">
    <button>Admin Login</button>
</form>

Different forms. Different routes. Same logic.


Step 6: Protect Admin Routes (Very Important)

Create middleware:

php artisan make:middleware AdminOnly
public function handle($request, Closure $next)
{
    if (!auth()->check() || !auth()->user()->isAdmin()) {
        abort(403);
    }

    return $next($request);
}

Register it in bootstrap/app.php:

$middleware->alias([
    'admin' => \App\Http\Middleware\AdminOnly::class,
]);

Use it:

Route::middleware(['auth', 'admin'])->group(function () {
    Route::get('/admin/dashboard', fn () => 'Admin Dashboard');
});

Common Beginner Mistakes (Avoid These)

  • Using the same login form for admin and users
  • Forgetting to check role after login
  • Putting role checks inside controllers instead of middleware
  • Mixing admin and user Blade files

Quick Summary

  • Use one users table with a role column
  • Separate routes, controllers, and views
  • Admin URLs should be prefixed (/admin)
  • Protect admin pages with middleware
  • Keep logic clean and readable

This structure scales well and doesn’t confuse future you.


FAQ (Beginner Questions)

1) Should I use two tables for admins and users?

Not unless you really need it. One table with roles is simpler and safer for beginners.


2) Can admins log in from the normal login page?

They shouldn’t. Separate login pages reduce security mistakes.


3) Can I add more roles later?

Yes. Just extend the role column (editor, manager, etc.) and reuse middleware.

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts

The Exact Laravel Skills Companies Pay For in 2026

Web Development

Stop Learning Laravel Like This (Do This Instead) in 2026

Web Development

Laravel Middleware in Laravel 12 (2026): Explained Simply, the New Way (With Real-World Examples)

Web Development