Laravel Native Multi-auth Password Reset
This pertains to Laravel 5.4, and probably above.
Example: You have another auth provider called 'customer'.
Tldr;
-
Copy both existing password controllers
-
Add a boker method in new ForgotPasswordController
-
Add a showLinkRequestForm in new ForgotPasswordController and point it to a new view
-
Update new ResetPasswordController:
Set $redirectTo path
set __constructt() middleware to guest:
Add broker method
Add showResetForm method, pointing to new view -
Create new password views (Copy existing /views/auth/passwords)
Update the post action in both email & reset templates.
Change the headings of each templete so can distigiwsh
Update login page template 'forgot my password' link -
Create new password broker (config/auth.php)
-
Edit the related user model
Add method 'sendPasswordResetNotification'
Make sure you import the notification (use App\Notifica...)
Make sure you import (& use) Notifiable (use Illumina..\Notifiations\Notifiable) -
Create new ResetPasswordNotification
Remember to change the url route in the email message -
Add routes to your new forgotten passsword/Reset controllers
Step 1 - Duplicate ForgotPasswordController & ResetPasswordController
Found in your: /var/www/app/Http/Controllers/Auth
The existing ForgotPasswordController & ResetPasswordController controllers can be used as templates.
cd /var/www/app/Http/Controllers/Auth
cat ForgotPasswordController.php > CustomerForgotPasswordController.php
cat ResetPasswordController.php > CustomerResetPasswordController.php
Rename the contoller classses
Because we just copied them, we need to rename is class appropriately:
vim CustomerForgotPasswordController.php
vim CustomerResetPasswordController.php
Change the class names accordingly:
Don't change your existing ForgotPasswordController or ResetPasswordController controllers!
- ForgotPasswordController becomes CustomerForgotPasswordController
- ResetPasswordController becomes CustomerResetPasswordController
Run composer dumpautoload to update the autoloader because of new classes in the classmap (see Composer Docs).
Step 2 Add the Password class to each Forgot/Reset password controller
The Password class (vendor/Illuminate/Support/Facades/Password.php
)extends the Facade class. It allows access to the static member functions that the Password class provides.
Edit each of the new controllers and add
use Password;
To include the password Facades.
Step 3 Add the Auth & Request Facade to the new CustomerResetPasswordController
use Auth;
use Illuminate\Http\Request;
Step 3.1 Ass the guard() method to ResetPasswordController
protected function guard()
{
return Auth::guard('customer');
}
Step 4 Set redirect location upon successful reset & login
Alter the protected $redirectTo
to where the customer should be directed to after resetting their password:
It will be defaulted to /home since we copied it earlier.
File: CustomerResetPasswordController.php
protected $redirectTo = '/customer';
Step 5 Set guest middle ware on each password controllers __construct
This prevents already logged in users from resetting their password
e.g.
public function __construct()
{
$this->middleware('customer');
}
Step 6 - Add a new password broker for your user type
File: www/config/auth.php
Find "Resetting Passwords" and you'll see the array of password brokers.
This requires you to add the name of the auth provider you with to use (e.g. customer').
Your providers array should be used as reference for the correct name of the provider.
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
'customers' => [
'provider' => 'customer',
'table' => 'password_resets',
'expire' => 60,
],
],
Note the 'table' element is password_resets
for both user types. This is OK, but you may simply create another table if desired.
Step 7 Use new password broker in your new password controllers
In both
- CustomerForgotPasswordController.php
- CustomerResetPasswordController.php
Add the following:
protected function broker()
{
return Password::broker('customers');
}
The argument passed to broker must be the one added in your www/config/auth.php
within the passwords array.
Step 8 - Create routes for you new password reset handlers
Copy the existing password routes, and then prefix them with the user type of the controllers you've just created (Customer) in this example.
Route::prefix('customer')->group(function() {
//Customer Password Reset routes Route::post('/password/email','Auth\CustomerForgotPasswordController@sendResetLinkEmail')->name('customer.password.email');
Route::post('/password/reset', 'Auth\CustomerResetPasswordController@reset');
Route::get('/password/reset', 'Auth\CustomerForgotPasswordController@showLinkRequestForm')->name('customer.password.request');
Route::get('/password/reset/{token}', 'Auth\CustomerResetPasswordController@showResetForm')->name('customer.password.reset');
});
Step 9 - Create Custom password Views for the user type
Navigate to /var/www/resources/views/auth/passwords
- email.blade.php
- reset.blade.php
Create copies of these, one for each user type you have in your multi-auth set-up e.g:
- email.blade.php
- reset.blade.php
- customer-email.blade.php
- customer-reset.blade.php
Edit the post action for customer-email.blade.php
and change it to customer.password.email
(referring to the named routes we just created in step 8). This ensures the request gets posted to the correct controller!
Edit the template to make it obvious this is the customer reset password form. Change the heading for example.
Step 10 - Override showLinkRequestForm
In your new CustomerForgotPasswordController
, override the showLinkRequestForm method to direct users to the correct reset password form.
You can find the template showLinkRequestForm method (which the standard auth (web) provider uses directly) in
vendor/laravel/framework/src/Illuminate/Foundation/Auth/SendsPasswordResetEmails.php
:
/**
* Display the form to request a password reset link.
*
* @return \Illuminate\Http\Response
*/
public function showLinkRequestForm()
{
return view('auth.passwords.email');
}
Open your CustomerForgotPasswordController
and implement this method, but change the returned view to 'auth.passwords.customer-email'. Example:
/**
* Display the form to request a password reset link.
*
* @return \Illuminate\Http\Response
*/
public function showLinkRequestForm()
{
return view('auth.passwords.customer-email');
}
Step 11 - Create Email Notification for user type
Navigate to /var/www/vendor/laravel/framework/src/Illuminate/Auth/Passwords
Open the file CanResetPassword.php
the and locate the method sendPasswordResetNotification
. Copy this method into you Customer model (in this example, your users will be different!)
Place the following in your App/Customer.php model
, making sure you generate a new Notification for this user type (see step 12)
/**
* Send the password reset notification.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new CustomerResetPasswordNotification($token));
}
Step 12 - Create CustomerResetPasswordNotification
A notification class needs to be created for the sending of email alert. Use artisan from the command line to achieve this:
php artisan make:notification CustomerResetPasswordNotification
This will create a new Notification class CustomerResetPasswordNotification in your app\Notifications
folder.
Edit your new email notification: vim app/Notifications/CustomerResetPasswordNotification.php
Add a $token public property, and pass this to the __construct:
File: app/Notifications/CustomerResetPasswordNotification.php
public $token;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($token)
{
$this->token = $token;
}
If you're wondering were the $token value comes from, it gets passed to the notification be the call to sendPasswordResetNotification()
in the Customer model (app/Customer.php) we just added.
Secondly, in the same file (CustomerResetPasswordNotification), customise the url action and email message that gets sent to the user:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('You are receiving this email because we received a password reset request for your account.')
->action('Reset Password', route('customer.password.reset', $thi->token))
->line('If you did not request a password reset, no further action is required.');
}
Note the use of the route()
function, which is given the route name (customer.password.reset) which we created earlier, and it's passed the $token
to be able to form a password reset link.
Step 11 - Add the Notification class to your user model
Edit your model vim app/Customer.php
and include the CustomerResetPasswordNotification you just created:
use App\Notifications\CustomerResetPasswordNotification;
class Customer extends Authenticatable
{
...
}
Step 12 - Add showResetForm method to your CustomerResetController
Navigate to file: /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Auth/ResetsPasswords.php
Copy the showResetForm
into your CustomerResetPasswordController.php and change the name of the returned view to auth.passwords.customer-reset
.
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* @param \Illuminate\Http\Request $request
* @param string|null $token
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request, $token = null)
{
return view('auth.passwords.customer-reset')->with(
['token' => $token, 'email' => $request->email]
);
}