First Step is to create a project and connect it to the database and run the migration.And See the usertable It is created automatically and check if the following fields are there or not
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
Run the migration if needed.. -> php artisan migrate
Now create AuthController php artisan make:controller AuthController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
class AuthController extends Controller
{
// Show login form
public function showLoginForm() {
return view('auth.login');
}
// Handle login
public function login(Request $request) {
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Invalid credentials',
]);
}
// Logout
public function logout(Request $request) {
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/login');
}
// Show registration form
public function showRegisterForm() {
return view('auth.register');
}
// Handle registration
public function register(Request $request) {
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6|confirmed',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
Auth::login($user);
return redirect('/dashboard');
}
}
you can write the login and registration form like this as well
This is register function
public function register(Request $request)
{
$credentials = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6|confirmed',
]);
$credentials['password'] = Hash::make($credentials['password']);
$user = User::create($credentials);
Auth::login($user);
return redirect('/dashboard');
}
This is login function
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials)) {
return redirect()->intended('/dashboard')->with('status', 'Logged in successfully!');
}
return back()->withErrors(['email' => 'Invalid credentials'])->onlyInput('email');
}
Define Routes
use App\Http\Controllers\AuthController;
// Guest routes
Route::middleware('guest')->group(function () {
Route::get('login', [AuthController::class, 'showLoginForm'])->name('login');
Route::post('login', [AuthController::class, 'login']);
Route::get('register', [AuthController::class, 'showRegisterForm'])->name('register');
Route::post('register', [AuthController::class, 'register']);
});
// Protected routes
Route::middleware('auth')->group(function () {
Route::post('logout', [AuthController::class, 'logout'])->name('logout');
Route::get('/dashboard', function () {
return view('dashboard');
});
});
Create blade view
Login: resources/views/auth/login.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<h2>Login</h2>
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="mb-3">
<label>Email</label>
<input type="email" name="email" class="form-control" value="{{ old('email') }}" required>
</div>
<div class="mb-3">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
@error('email')
<div class="text-danger">{{ $message }}</div>
@enderror
<button type="submit" class="btn btn-primary">Login</button>
<a href="{{ route('register') }}" class="btn btn-link">Register</a>
</form>
</div>
@endsection
Register: resources/views/auth/register.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<h2>Register</h2>
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="mb-3">
<label>Name</label>
<input type="text" name="name" class="form-control" value="{{ old('name') }}" required>
</div>
<div class="mb-3">
<label>Email</label>
<input type="email" name="email" class="form-control" value="{{ old('email') }}" required>
</div>
<div class="mb-3">
<label>Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="mb-3">
<label>Confirm Password</label>
<input type="password" name="password_confirmation" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
<a href="{{ route('login') }}" class="btn btn-link">Login</a>
</form>
</div>
@endsection
Dashboard: resources/views/dashboard.blade.php
@extends('layouts.app')
@section('content')
<h1>Welcome, {{ auth()->user()->name }}</h1>
<p>This is your dashboard.</p>
@endsection
5️⃣ Update layouts/app.blade.php
<!-- Sidebar and main content structure -->
<div class="container-fluid">
<div class="row">
<nav class="col-md-3 col-lg-2 sidebar">
<a href="/dashboard">Dashboard</a>
<a href="/posts/create">Create Post</a>
@auth
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="btn btn-link p-0 mt-3">Logout</button>
</form>
@endauth
</nav>
<main class="col-md-9 col-lg-10 p-4">
@yield('content')
</main>
</div>
</div>
✅ Now you have a fully functional, clean, custom auth system in Laravel 12, without Breeze or Jetstream.
-
/login→ login form -
/register→ register form -
/dashboard→ protected dashboard -
Logout works via POST form
Here is github link : https://github.com/Binaryx01/custom-login-single-user
