Forgot Password Laravel Setup
October 19, 2024 · AI Conversations
### Step 1: Set Up Email Configuration
Make sure your `.env` file is properly configured to send emails. Update these lines with your mail service details:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=your_email@example.com
MAIL_FROM_NAME="${APP_NAME}"
### Step 2: Migrations
Laravel comes with a migration to handle password resets. You can find it in the `database/migrations` folder, specifically the migration file called `create_password_resets_table.php`. If it's not present, you can create it manually:
php artisan make:migration create_password_resets_table
Then in the migration file:
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Run the migration:
php artisan migrate
### Step 3: Routes
Laravel already includes password reset routes. You can enable them by editing the `routes/web.php` file:
Auth::routes(['verify' => true]);
This will register the necessary routes for password reset:
– **GET** `password/reset` → Form to request reset email
– **POST** `password/email` → Send reset link
– **GET** `password/reset/{token}` → Form to reset password
– **POST** `password/reset` → Update password in database
### Step 4: Controllers
Laravel provides a `ForgotPasswordController` and `ResetPasswordController` out of the box. These handle the entire process of sending reset links and updating the password. You can find them in `app/Http/Controllers/Auth`.
If you need to customize anything, you can override methods in these controllers.
### Step 5: Views
Laravel's default authentication scaffolding already includes the views necessary for password resets. You can publish them to customize:
php artisan ui:auth
If you are using Inertia.js with Vue, you will need to create Vue components for the reset forms.
For example, you can create a `ForgotPassword.vue` component:
<template>
<form @submit.prevent="submit">
<input type="email" v-model="form.email" placeholder="Email" required />
<button type="submit">Send Password Reset Link</button>
</form>
</template>
<script>
export default {
data() {
return {
form: {
email: ''
}
}
},
methods: {
submit() {
this.$inertia.post('/password/email', this.form);
}
}
}
</script>
Similarly, you can create a `ResetPassword.vue` component:
<template>
<form @submit.prevent="submit">
<input type="hidden" v-model="form.token" />
<input type="email" v-model="form.email" placeholder="Email" required />
<input type="password" v-model="form.password" placeholder="New Password" required />
<input type="password" v-model="form.password_confirmation" placeholder="Confirm Password" required />
<button type="submit">Reset Password</button>
</form>
</template>
<script>
export default {
props: ['token', 'email'],
data() {
return {
form: {
token: this.token,
email: this.email || '',
password: '',
password_confirmation: ''
}
}
},
methods: {
submit() {
this.$inertia.post('/password/reset', this.form);
}
}
}
</script>
### Step 6: Customizing Email Notifications
To customize the reset email, you can create a custom notification by extending `IlluminateAuthNotificationsResetPassword`.
php artisan make:notification ResetPasswordNotification
In the `toMail` method, customize the email content:
use IlluminateNotificationsMessagesMailMessage;
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Reset Password Notification')
->line('You are receiving this email because we received a password reset request for your account.')
->action('Reset Password', url('/password/reset', $this->token))
->line('If you did not request a password reset, no further action is required.');
}
### Final Steps
– Ensure you have a valid mail configuration for sending the password reset link.
– Customize views or notifications as necessary for your application.
This will set up a complete forgot password feature in your Laravel application.
### Step 1: Set Up Email Configuration
Ensure your `.env` file is properly configured for sending emails. Update the following:
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=your_email@example.com
MAIL_FROM_NAME="${APP_NAME}"
### Step 2: Enable Routes
Laravel already provides password reset routes. In the `routes/web.php`, you can enable them like this:
Auth::routes(['verify' => true]);
This will enable routes like:
– **GET** `password/reset` (form to request reset link)
– **POST** `password/email` (send reset link)
– **GET** `password/reset/{token}` (form to reset password)
– **POST** `password/reset` (update password)
### Step 3: Create Blade Views
Laravel includes default views for the password reset feature, but you can create custom Blade templates for a customized experience.
#### (1) Forgot Password Form (`resources/views/auth/passwords/email.blade.php`)
This form allows users to request a password reset link.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('password.email') }}">
@csrf
<div class="form-group">
<label for="email">{{ __('E-Mail Address') }}</label>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
#### (2) Password Reset Form (`resources/views/auth/passwords/reset.blade.php`)
This form allows users to reset their password after clicking the link sent to their email.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="form-group">
<label for="email">{{ __('E-Mail Address') }}</label>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<label for="password">{{ __('Password') }}</label>
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<label for="password-confirm">{{ __('Confirm Password') }}</label>
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
### Step 4: Customize Email Notification (Optional)
If you want to customize the password reset email, create a custom notification by running:
php artisan make:notification ResetPasswordNotification
In the generated notification (`app/Notifications/ResetPasswordNotification.php`), you can customize the content of the email:
use IlluminateNotificationsMessagesMailMessage;
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Reset Your Password')
->line('We received a request to reset your password.')
->action('Reset Password', url('password/reset', $this->token))
->line('If you didn’t request this, please ignore this email.');
}
### Step 5: Mail Configuration
Ensure your `.env` has the correct mail settings so emails can be sent out for password resets.
### Step 6: Testing the Feature
– Navigate to `/password/reset` to test the "Forgot Password" feature.
– Submit the email form, and you should receive an email with a password reset link.
– Follow the link to reset the password.
This sets up the "Forgot Password" feature using Blade templates in your Laravel application.
### Step 1: Set Up Coach Guard in `config/auth.php`
Ensure that you have a separate guard for "coach" in your `config/auth.php` file:
'guards' => [
'coach' => [
'driver' => 'session',
'provider' => 'coaches',
],
// other guards...
],
'providers' => [
'coaches' => [
'driver' => 'eloquent',
'model' => AppModelsCoach::class,
],
// other providers...
],
### Step 2: Customize `PasswordResetLinkController` for Coach Guard
In your `PasswordResetLinkController`, you can modify the `store` method to ensure it handles password reset for the "coach" guard.
Here's how you can do it:
namespace AppHttpControllersAuth;
use AppHttpControllersController;
use IlluminateHttpRedirectResponse;
use IlluminateHttpRequest;
use IlluminateSupportFacadesPassword;
use IlluminateViewView;
class PasswordResetLinkController extends Controller
{
/**
* Display the password reset link request view for the coach guard.
*/
public function create(): View
{
return view('coach.auth.forgot-password');
}
/**
* Handle an incoming password reset link request for the coach guard.
*
* @throws IlluminateValidationValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email'],
]);
// Specify the broker for the coach guard
$status = Password::broker('coaches')->sendResetLink(
$request->only('email')
);
return $status == Password::RESET_LINK_SENT
? back()->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}
### Step 3: Configure Password Broker for Coach
In `config/auth.php`, you need to add a custom password broker for "coach" users. This tells Laravel how to handle password resets for this specific guard:
'passwords' => [
'coaches' => [
'provider' => 'coaches',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
// other password brokers...
],
### Step 4: Update the Password Reset View for Coach
Ensure that the password reset view is customized for "coach". If you have a specific folder for the "coach" guard, the view should be something like `resources/views/coach/auth/forgot-password.blade.php`.
#### Example `forgot-password.blade.php` for Coach:
@extends('coach.layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('coach.password.email') }}">
@csrf
<div class="form-group">
<label for="email">{{ __('E-Mail Address') }}</label>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
### Step 5: Update Routes for Coach
In your `routes/web.php` or wherever you define the coach routes, ensure that you have the password reset routes for the "coach" guard:
Route::prefix('coach')->name('coach.')->group(function () {
Route::get('forgot-password', [AppHttpControllersAuthPasswordResetLinkController::class, 'create'])->name('password.request');
Route::post('forgot-password', [AppHttpControllersAuthPasswordResetLinkController::class, 'store'])->name('password.email');
Route::get('reset-password/{token}', [AppHttpControllersAuthNewPasswordController::class, 'create'])->name('password.reset');
Route::post('reset-password', [AppHttpControllersAuthNewPasswordController::class, 'store'])->name('password.update');
});
This ensures that the password reset functionality works for the "coach" guard specifically.
### Final Step: Test the Functionality
– Visit `/coach/forgot-password`.
– Enter an email of a coach user and verify that the reset link is sent.
– Follow the link and reset the password to ensure everything is working as expected.
This setup should now correctly handle password resets for the "coach" guard in your Laravel application.
### Updated `NewPasswordController` for the Coach Guard
namespace AppHttpControllersAuth;
use AppHttpControllersController;
use IlluminateAuthEventsPasswordReset;
use IlluminateHttpRedirectResponse;
use IlluminateHttpRequest;
use IlluminateSupportFacadesHash;
use IlluminateSupportFacadesPassword;
use IlluminateSupportStr;
use IlluminateValidationRules;
use IlluminateViewView;
class NewPasswordController extends Controller
{
/**
* Display the password reset view for the coach guard.
*/
public function create(Request $request): View
{
return view('coach.auth.reset-password', ['request' => $request]);
}
/**
* Handle an incoming new password request for the coach guard.
*
* @throws IlluminateValidationValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'token' => ['required'],
'email' => ['required', 'email'],
'password' => ['required', 'confirmed', RulesPassword::defaults()],
]);
// Attempt to reset the coach's password using the 'coaches' broker
$status = Password::broker('coaches')->reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user) use ($request) {
$user->forceFill([
'password' => Hash::make($request->password),
'remember_token' => Str::random(60),
])->save();
event(new PasswordReset($user));
}
);
// Redirect based on success or failure of the password reset
return $status == Password::PASSWORD_RESET
? redirect()->route('coach.login')->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}
### Explanation of Key Changes:
1. **Password Broker for Coaches**:
– In the `Password::broker('coaches')` method, we specify the "coaches" broker. This ensures that the password reset is done through the "coach" guard.
2. **Custom View**:
– The view for password reset is customized for the "coach" guard: `return view('coach.auth.reset-password', ['request' => $request]);`. Ensure that you have the corresponding Blade view in `resources/views/coach/auth/reset-password.blade.php`.
3. **Login Route**:
– After a successful password reset, the controller redirects to the "coach" login route: `redirect()->route('coach.login')`.
### Step 1: Define Password Broker in `config/auth.php`
Ensure that the "coaches" broker is defined in `config/auth.php`:
'passwords' => [
'coaches' => [
'provider' => 'coaches',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
### Step 2: Update Routes for Coach
Ensure that the reset password routes for the "coach" guard are set up in your `routes/web.php` file:
Route::prefix('coach')->name('coach.')->group(function () {
Route::get('reset-password/{token}', [AppHttpControllersAuthNewPasswordController::class, 'create'])->name('password.reset');
Route::post('reset-password', [AppHttpControllersAuthNewPasswordController::class, 'store'])->name('password.update');
});
### Step 3: Blade View for Reset Password Form
In your `resources/views/coach/auth/reset-password.blade.php` file, create the form for resetting the password.
Here’s an example of how the Blade view could look:
@extends('coach.layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
<form method="POST" action="{{ route('coach.password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $request->token }}">
<div class="form-group">
<label for="email">{{ __('E-Mail Address') }}</label>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $request->email ?? old('email') }}" required autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<label for="password">{{ __('Password') }}</label>
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required>
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group mt-3">
<label for="password-confirm">{{ __('Confirm Password') }}</label>
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
### Final Step: Test the Password Reset
Now, you should be able to reset passwords for coaches by visiting the coach's password reset URL, submitting a valid email, and resetting the password via the link sent in the email.