As a Laravel enthusiast, I’m excited to share how to implement password reset functionality in Laravel 12. This feature is a must-have for any web app, ensuring users can securely recover their accounts. Laravel 12, with its robust authentication system, makes this process seamless.
In this guide, I’ll walk you through each step, from setup to customization, using simple language and practical examples.
Implementing a password reset feature in Laravel 12 is straightforward, thanks to its built-in authentication tools like Laravel Breeze or Fortify. Below, I’ll guide you through the process with clear steps and code snippets to ensure a secure and user-friendly experience.
First, ensure you have a Laravel 12 installed. Open your terminal and create a new project:
composer create-project --prefer-dist laravel/laravel password-reset-app
cd password-reset-app
Run the development server:
php artisan serve
This sets up a fresh Laravel 12 application. Ensure you have a database (MySQL, PostgreSQL, or SQLite) configured in the .env
file.
Laravel Breeze provides a quick way to scaffold authentication, including password reset. Install it using:
composer require laravel/breeze --dev
php artisan breeze:install
Choose the Blade stack for simplicity, and run:
npm install && npm run dev
php artisan migrate
This command sets up the authentication system, including login, registration, and password reset views.
Ensure your App\Models\User
model uses the Notifiable
trait and implements the CanResetPassword
contract. Laravel 12’s default User
model already includes these:
namespace App\Models;
use Illuminate\Contracts\Auth\CanResetPassword;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements CanResetPassword
{
use Notifiable;
// Other model properties and methods
}
This enables sending password reset notifications.
Laravel requires a password_resets
table to store reset tokens. The migration is included by default. Run:
php artisan migrate
This creates the password_resets
table with email
, token
, and created_at
columns.
Password reset links are sent via email, so configure your mail settings in the env file. For testing, use a service like Mailtrap:
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
[email protected]
MAIL_FROM_NAME="${APP_NAME}"
Test email configuration to ensure emails are sent correctly.
Laravel Breeze sets up the necessary routes in routes/auth.php
. Verify the following routes exist:
use App\Http\Controllers\Auth\ForgotPasswordController;
use App\Http\Controllers\Auth\ResetPasswordController;
Route::get('password/reset', [ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request');
Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email');
Route::get('password/reset/{token}', [ResetPasswordController::class, 'showResetForm'])->name('password.reset');
Route::post('password/reset', [ResetPasswordController::class, 'reset'])->name('password.update');
These routes handle the password reset request form, email sending, reset form display, and password update.
Customize the email template by overriding the sendPasswordResetNotification
method in the User
model:
use App\Notifications\CustomResetPassword;
public function sendPasswordResetNotification($token)
{
$this->notify(new CustomResetPassword($token));
}
Create a notification class:
php artisan make:notification CustomResetPassword
Edit app/Notifications/CustomResetPassword.php
:
namespace App\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class CustomResetPassword extends Notification
{
public $token;
public function __construct($token)
{
$this->token = $token;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Reset Your Password')
->line('Click the button below to reset your password.')
->action('Reset Password', url('/password/reset/'.$this->token))
->line('If you didn’t request this, ignore this email.');
}
}
This creates a branded email with a clickable reset link.
Edit the Blade templates in resources/views/auth/
to match your app’s design. For example, modify password-email.blade.php
:
<!DOCTYPE html>
<html>
<head>
<title>Reset Password</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h2>Reset Password</h2>
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('password.email') }}">
@csrf
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" name="email" class="form-control @error('email') is-invalid @enderror" required>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">Send Password Reset Link</button>
</form>
</div>
</body>
</html>
Similarly, update reset-password.blade.php
for the reset form.
/password/reset
and enter a registered email.app/Providers/RouteServiceProvider.php
:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
protected function configureRateLimiting()
{
RateLimiter::for('password-reset', function () {
return Limit::perMinute(5)->by(request()->ip());
});
}
auth:clear-resets
command to remove expired tokens:
use Illuminate\Support\Facades\Schedule;
Schedule::command('auth:clear-resets')->everyFifteenMinutes();
Log password reset attempts for security auditing. Create a middleware:
php artisan make:middleware LogPasswordReset
Edit app/Http/Middleware/LogPasswordReset.php
:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
class LogPasswordReset
{
public function handle($request, Closure $next)
{
Log::info('Password reset attempt', [
'email' => $request->email,
'ip' => $request->ip(),
]);
return $next($request);
}
}
Register it in app/Http/Kernel.php
and apply it to the reset routes.
Implementing password reset functionality in Laravel 12 is both powerful and user-friendly, thanks to its built-in authentication tools. By following this guide, you’ve created a secure, customizable password reset flow that enhances user experience and app security.
Laravel’s flexibility allows you to tailor the feature to your needs, from custom emails to advanced security measures. Keep exploring Laravel 12’s documentation for more ways to optimize authentication and make your app stand out.
No, you can manually set up password reset using Laravel Fortify or custom routes and controllers. Breeze just simplifies it with built-in scaffolding.
Use a service like Mailtrap to capture and preview emails in a test environment. Just configure it in your env file.
Check your mail driver settings, inspect spam folders, and ensure the correct email address was entered. Also, log email dispatch attempts for debugging.
Yes. You can use ResetPassword::createUrlUsing
in AppServiceProvider
to define custom password reset link behavior and structure.
Use rate limiting, input validation, logging, and automatic token expiration to prevent misuse and ensure a secure password reset flow.
You might also like: