Custom Laravel Authentication with Email Verification (Step by Step Guide)

In this article, you will learn how to create a custom authentication system in Laravel step by step, including user registration, login and logout, sending an email verification link, and validating user input using custom Requests. The article includes ready-to-use code examples with detailed explanations to make implementation easier.

Author: hamza ougjjou
Published: Aug 22, 2025
Reading time: 5 min read
Custom Laravel Authentication with Email Verification (Step by Step Guide)

Setting Up the Environment

First, make sure Laravel is installed. You can create a new Laravel project by running the following command:


laravel new laravel-custom-auth
    

Or follow the official guide in the Laravel Documentation

After downloading the project files, edit the migration file for the users table.


...
public function up(): void
{
    Schema::create('users', function (Blueprint $table) {
        $table->id(); // Unique user ID
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable(); // Used to verify the user's email
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}
...
    

Run the migration to create the users table.


php artisan migrate
    

Modify the User Model

Update the User model so it extends the Authenticatable class, allowing authentication features such as login and logout. Also, implement the MustVerifyEmail interface to enable email verification after registration.

User.php File

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;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];
}
    

Creating the AuthController

The AuthController handles all authentication logic such as: registration, login, logout, and sending email verification links.


php artisan make:controller auth\AuthController
    

Here is the AuthController code with explanations:


namespace App\Http\Controllers\api;

use App\Http\Controllers\Controller;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RegisterRequest;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    // Show registration page
    public function register()
    {
        return view('auth.register');
    }

    public function register_store(RegisterRequest $request)
    {
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        // Log in the user
        Auth::login($user);

        // Send verification email
        $user->sendEmailVerificationNotification();

        // Redirect to profile page
        return redirect()->route('profile')
            ->with('success', 'Registration successful! Welcome.');
    }

    // Show login page
    public function login(Request $request)
    {
        return view('auth.login');
    }

    public function login_store(LoginRequest $request)
    {
        // Attempt login using email and password
        if (Auth::attempt($request->only('email', 'password'))) {

            // Regenerate session for security
            $request->session()->regenerate();

            return redirect()->route('profile')
                ->with('success', 'Login successful! Welcome.');
        }

        // Invalid credentials
        return back()->withErrors([
            'email' => 'The provided credentials are incorrect.',
        ])->onlyInput('email');
    }

    public function logout()
    {
        // Logout user
        Auth::logout();

        // Redirect to homepage
        return redirect()->route('home')
            ->with('success', 'You have been logged out successfully.');
    }
}
    

Creating LoginRequest and RegisterRequest

These request classes validate user input before saving data into the database.

RegisterRequest File


php artisan make:request RegisterRequest
        

The RegisterRequest file will be located at:

App\Http\Requests\RegisterRequest.php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => 'required|string|min:2|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|string|min:6',
            'password_confirmation' => 'required|string|min:6|same:password',
        ];
    }

    public function messages(): array
    {
        return [
            'name.required' => 'The name field is required.',
            'email.required' => 'The email field is required.',
            'email.email' => 'Please provide a valid email address.',
            'email.unique' => 'This email is already registered.',
            'password.required' => 'The password field is required.',
            'password.min' => 'The password must be at least 6 characters long.',
            'password.confirmed' => 'The password confirmation does not match.',
        ];
    }
}
        

LoginRequest File


php artisan make:request LoginRequest
        

The LoginRequest file will be located at:

App\Http\Requests\LoginRequest.php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class LoginRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'email' => 'required|email',
            'password' => 'required|min:6',
        ];
    }

    public function messages()
    {
        return [
            'email.required' => 'Email is required.',
            'email.email' => 'Please provide a valid email address.',
            'password.required' => 'Password is required.',
            'password.min' => 'Password must be at least 6 characters long.',
        ];
    }
}
        

Defining Routes

routes\web.php

use App\Http\Controllers\api\AuthController;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Auth\EmailVerificationRequest;

Route::view("/", "welcome")->name("home");

Route::get('/login', [AuthController::class , 'login'])->name('login');
Route::post('/login', [AuthController::class , 'login_store'])->name('login.store');

Route::get('/register', [AuthController::class , 'register'])->name('register');
Route::post('/register', [AuthController::class , 'register_store'])->name('register.store');

Route::post('/logout', [AuthController::class , 'logout'])
    ->name('logout')
    ->middleware('auth');

Route::view('/profile', "auth.profile")
    ->name('profile')
    ->middleware('auth');

// Email Verification Routes
Route::view('/email/verify', "auth.verify-email")
    ->middleware('auth')
    ->name('verification.notice');

Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
    $request->fulfill();
    return redirect('/profile');
})->middleware(['auth', 'signed'])
  ->name('verification.verify');

Route::post('/email/verification-notification', function (Illuminate\Http\Request $request) {
    $request->user()->sendEmailVerificationNotification();
    return back()->with('message', 'Verification email sent!');
})->middleware(['auth', 'throttle:6,1'])
  ->name('verification.resend');
    

Views Files resources\views

Laravel views structure

All view files are attached to this article and can be downloaded from Here



If you have any questions, leave them in the comments section or contact us
Advertisement

Comments

avatar

lmYbQXhSccVaXepZCQJvAl

6 months ago

WvjzmQOFQvKaBiHwjhWKEUU

avatar

TWhiiKzPNyryTQhoTBpkP

6 months ago

McLIUjUvYUVmIZkXdBEh

Related Articles