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&/register→ Normal users/admin/login&/admin/register→ Admins- Separate views (Blade files)
- Separate controllers
- One shared
Usermodel (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 userrole = 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.
Projects to explore next
Source-code projects from the KritiMyantra catalogue. Check each project's details before buying.
Flask Authentication System (Free Version) - Kritim Yantra
🛠 Features✔ Google & GitHub Authentication✔ User Registration & Login✔ Profile/Dashboard Access✔ Secure & Mi...
Flask Blog CMS with Admin Dashboard — Python Source Code
A Flask-based blogging website with a built-in admin dashboard. Manage articles, images, categories, tags and featured p...
Laravel 12 + ReactJS Starter Kit: Add Multi-Language Support (Arabic, English, Spanish) with Blog CRUD
🚀 Installation & Setup Download & Extract Get the ZIP from kritimyantra.com and extract it. Includes preconfigu...
Comments
No comments yet. Be the first to comment.
Sign in to join the discussion.