The blog post "Laravel User Login and Password Recovery: A Step-by-Step Guide" walks you through the process of setting up secure user authentication and password recovery by email in Laravel. Covering topics such as configuring the database of reset_password, customizing login views and controllers, and implementing password reset functionality, this guide ensures a comprehensive understanding. With practical tips on testing and enhancing security measures, the blog aims to empower readers to implement these features effectively in their Laravel applications.
To set up SMTP in your Laravel application using the .env file, you need to configure the following variables related to your email provider. Below is an example .env file snippet for setting up SMTP with some common email service providers:
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com // here use gmail.com
MAIL_PORT=587
MAIL_USERNAME=sndp@gmail.com // write your email
MAIL_PASSWORD=your_email_app_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="sndp@gmail.com" // write your email
MAIL_FROM_NAME="${APP_NAME}"
Note :
Clear Config Cache:
After making changes to your .env file, run the following Artisan command to clear the configuration cache:
php artisan config:cache
Run the following Artisan command to generate the controller:
php artisan make:controller ForgotPasswordController
Laravel already provides a default Database Table Which name is password_resets table . Storing user emails and generating tokens. here email column make is primary key.
Code - php artisan make:model PasswordReset
Open the generated PasswordReset.php model file located in the app→Models→ directory.
Model Code :
protected $table = 'password_resets'; // table name and model name are different
public $timestamps = "false"; // Disable timestamps for this model
protected $primaryKey = "email"; // Set 'email' as the primary key
protected $fillable = [
'email',
'token',
'created_at',
];
Create a "Forget Password" page showcasing an input box and a password reset button. Users enter their correct email and click the reset button to initiate the process.
View name - forget-password.blade.php
@if(session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<form action="{{route('forgetPassword')}}" method="POST">
@csrf
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" placeholder="Enter Email id" class="form-control">
@error('email')
<p class="text-danger">{{$message}}</p>
@enderror
</div>
<div class="form-group row mb-0">
<a href="{{url('login')}}">Login </a>
</div>
<br>
<input type="submit" name="submit" value="Forgot Password" class="btn btn-primary">
</form>
Route : Open View.php file from Route directory and Create Two Route get and post for this page.
import - use App\Http\Controllers\ForgotPasswordController;
// forgot password page route
Route::get('forget-Password',[ForgotPasswordController::class,'forgotPasswordLoad']);
Route::post('forget-Password',[ForgotPasswordController::class,'forgotPassword'])->name('forgetPassword');
Open the login.blade.php file located in the resources→views→ directory.
Add Anchor Tag for Forgotten Password:
Inside the login form, add an anchor tag (<a>) with an href attribute pointing to the route or URL where users can initiate the password recovery process. This is often a "Forgot Password" page.
Add HTML Code :
<a href="{{url('/forget-Password')}}"> Forgot Your Password? </a>
Open ForgotPasswordController.php file located in the app→Http→Controllers directory.
First Route function : for view load
public function forgotPasswordLoad()
{
return view('forget-password');
}
2nd Route function : for check email, send email with link etc.
Import bellow lines of controller :
use App\Models\passwordReset; // this is model import
use Illuminate\Support\Facades\Mail; // Import the Mail facade for sending emails
use Illuminate\Support\Facades\URL; //Import the URL facade for generating URLs, especially signed routes
use Illuminate\Support\Carbon; // Import the Carbon class for handling date and time
use Illuminate\Support\Str; // Import the Str class for string manipulation, including generating random strin
use App\Models\User; // this is user model where user all details store
public function forgotPassword(Request $request)
{
try {
// Check if the user with the provided email exists
$user = User::where('email', $request->email)->get();
if (count($user) > 0) {
// Generate a random token
$token = Str::random(40);
// Build the password reset URL
$domain = URL::to('/');
$url = $domain . '/reset-password?token=' . $token;
// Prepare data for the email template
$data['url'] = $url;
$data['email'] = $request->email;
$data['title'] = "Forget password reset";
$data['body'] = "Please click the link below to reset your password.";
// Send the password reset email
Mail::send('forgotPasswordMail', ['data' => $data], function ($message) use ($data) {
$message->to($data['email'])->subject($data['title']);
});
// Get the current date and time
$dateTime = Carbon::now()->format('Y-m-d H:i:s');
// Update or insert the password reset token in the database
PasswordReset::updateOrInsert(
['email' => $request->email],
[
'email' => $request->email,
'token' => $token,
'created_at' => $dateTime,
]
);
return back()->with('success', 'Please check your email address for the password reset link.');
} else {
return back()->with('error', 'Email does not exist.');
}
} catch (\Exception $e) {
return back()->with('error', $e->getMessage());
}
}
This view page send user email for changing password.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Forgot Password</title>
</head>
<body>
<h2>{{ $data['title'] }}</h2>
<p>{{ $data['body'] }}</p>
<p><a href="{{ $data['url'] }}">Reset Password</a></p>
<p>If you didn't request a password reset, please ignore this email.</p>
<p>Thank you,<br>
Your Application Team</p>
</body>
</html>
// for reset password
Route::get('reset-password',[ForgotPasswordController::class,'resetPasswordLoad']); // load reset page
Route::post('reset-password',[ForgotPasswordController::class,'resetPassword'])->name('resetPassword'); // store password
import this line for make hash password - use Illuminate\Support\Facades\Hash;
// load page condition base if user change URL any character , page redirect 400 page not found
public function resetPasswordLoad(Request $request)
{
// Retrieve the password reset data based on the token
$resetData = passwordReset::where('token',$request->token)->get();
if(isset($request->token) && count($resetData) >0 )
{
$user = User::where('email',$resetData[0]['email'])->get();
// Pass the user data to the 'reset_password' view
return view('reset_password',compact('user'));
}else
{
// Redirect to a 404 view if the token is invalid or not found
return view('404');
}
}
public function resetPassword(Request $request)
{
// Validate the incoming request data
$request ->validate([
'password' => 'required | min:6|confirmed',
]);
// Find the user in the database based on the provided ID
$user = User::find($request->id);
// Update the user's password with the hashed new password
$user ->password = Hash::make($request->password);
$user->save();
// Delete the password reset entry for the user's email from the PasswordReset table
passwordReset::where('email', $user->email)->delete();
return "<h2>Password reset successfully</h2>";
}
view name - 404.blade.php
code :
<h2>404 page is expired</h2>
@if(session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
<form action="{{route('resetPassword')}}" method="POST">
@csrf
<input type="hidden" name="id" value="{{$user[0]['id']}}">
<div class="form-group">
<label for="password">Enter Password</label>
<input type="password" id="password" name="password" placeholder="Enter password" class="form-control">
@error('password')
<p class="text-danger">{{$message}}</p>
@enderror
</div>
<div class="form-group">
<label for="passwords">Re-Enter Password</label>
<input type="password" id="passwords" name="password_confirmation" placeholder="ReEnter password" class="form-control">
@error('password')
<p class="text-danger">{{$message}}</p>
@enderror
</div>
<br>
<input type="submit" name="submit" value="Reset Password" class="btn btn-primary">
</form>
<br>
<a href="{{route('login')}}">Login</a>
I'm a dedicated full-stack developer, entrepreneur, and the proud owner of ocec.org.in , hailing from the vibrant country of India. My passion lies in creating informative tutorials and sharing valuable tips that empower fellow artisans in their journey. With a deep-rooted love for technology, I've been an ardent enthusiast of PHP, Laravel, Angular, Vue, Node, JavaScript, jQuery, Codeigniter, and Bootstrap from their earliest days. My philosophy revolves around the values of hard work and unwavering consistency, driving me to continuously explore, create, and share my knowledge with the tech community.
helllo