Vue Js Reset Password With Laravel API (Part 3)
In this article, we will discuss “How to make Vue Js Reset Password With Laravel API”. In our previous article on this series, you will learn Laravel JWT Authentication and Vue Js application setup with Vue Auth and Laravel JWT Auth. I will recommend you to read out both of the previous parts for better understanding. You can skip those if you are looking only for the specific User Reset Password functionality using Laravel API’s.
Table of Contents
Handle Password Reset Request
We are using our “AuthController” to handle password reset functionality. Add the following traits to our Authentication Controller.
Illuminate\Foundation\Auth\SendsPasswordResetEmails; Illuminate\Foundation\Auth\ResetsPasswords;
After that, you need to add the following function which handles the notification mail. End user receives a mail on his/her email. Where they click on the reset link, then the user clicks and redirect to our application to reset the password.
/** * Send password reset link. */ public function sendPasswordResetLink(Request $request) { return $this->sendResetLinkEmail($request); }
Note that, sendResetLinkEmail method does not return JSON response for our API. Because it’s defined for web base functionality so we need to override the response for our API.
The response is manage by sendResetLinkResponse and sendResetLinkFailedResponse function. You can found these functions in the SendsPasswordResetEmails trait.
Add the following function in your authentication controller.
/** * Get the response for a successful password reset link. * * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetLinkResponse(Request $request, $response) { return response()->json([ 'message' => 'Password reset email sent.', 'data' => $response ]); } /** * Get the response for a failed password reset link. * * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetLinkFailedResponse(Request $request, $response) { return response()->json(['message' => 'Email could not be sent to this email address.']); }
Custom Email Notification
You need to use the following artisan command to create a custom notification.
php artisan make:notification MailResetPasswordNotification
You will found the newly generated notification class at “app/Notifications”.
We need to extend the “Illuminate\Auth\Notifications\ResetPassword” and override the “toMail” function. After updating all the code notification class looks like below, you can update your “MailResetPasswordNotification.php” with following code snippet.
<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Auth\Notifications\ResetPassword; class MailResetPasswordNotification extends ResetPassword { use Queueable; /** * Create a new notification instance. * * @return void */ public function __construct($token) { parent::__construct($token) } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['mail']; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $link = url( "/reset-password/".$this->token ); return ( new MailMessage ) ->subject( 'Reset Password Notification' ) ->line( "Hello! You are receiving this email because we received a password reset request for your account." ) ->action( 'Reset Password', $link ) ->line( "This password reset link will expire in ".config('auth.passwords.users.expire')." minutes" ) ->line( "If you did not request a password reset, no further action is required." ); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } }
In this notification class, I’m using the ResetPassword trait. Here, I override the toMail function where we use our Vue Js app URL to handle the reset password form. In this URL we are sending a unique token. A token is mandatory to add in this mail otherwise the notification sending is totally meaningless.
To finalize our notification, we need to update our User Model. Please check the below mention code snippet, and add in your User Model.
/** * Override the mail body for reset password notification mail. */ public function sendPasswordResetNotification($token) { $this->notify(new \App\Notifications\MailResetPasswordNotification($token)); }
Create API Routes
Now, we need to create routes which handle notification mail and update password. So open the “routes/api.php” and update your routes.
Route::prefix('v1')->group(function () { Route::prefix('auth')->group(function () { ... // Send reset password mail Route::post('reset-password', 'AuthController@sendPasswordResetLink'); // handle reset password form process Route::post('reset/password', 'AuthController@callResetPassword'); ... }); });
Reset Password
As per the route, which handles the reset password process. I’m creating a “callResetPassword” method in the AuthController and make sure this function can be accessed by unauthenticated users. So the user can easily process the reset password request.
/** * Handle reset password */ public function callResetPassword(Request $request) { return $this->reset($request); }
This function calls the reset method, this method sets the new password, save the user, set a different remember token for the user. But, we are making this functionality for the Vue Js and using JWT authentication in our API so we don’t need to store a remember token. Check the following resetPassword method and add this in your controller.
/** * Reset the given user's password. * * @param \Illuminate\Contracts\Auth\CanResetPassword $user * @param string $password * @return void */ protected function resetPassword($user, $password) { $user->password = Hash::make($password); $user->save(); event(new PasswordReset($user)); }
If you face issues to use PasswordReset and Hash in your controller. Then add the following code snippet in your AuthController before the start of your controller class.
use Hash; use Illuminate\Auth\Events\PasswordReset;
After that, we need to manage the response. Because as per our API, we need a JSON response. But, the default method response is not in JSON format so we need to override the response method for our API’s.
Add the following functions in your AuthController to override the reset password response.
/** * Get the response for a successful password reset. * * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetResponse(Request $request, $response) { return response()->json(['message' => 'Password reset successfully.']); } /** * Get the response for a failed password reset. * * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetFailedResponse(Request $request, $response) { return response()->json(['message' => 'Failed, Invalid Token.']); }
Vue Js Application Route
Here I’m creating two routes, first for a reset link request form and second for processing a reset password form. So open your “resources/js/router.js” and add the following routes.
const routes = [ ... { path: '/reset-password', name: 'reset-password', component: ForgotPassword, meta: { auth:false } }, { path: '/reset-password/:token', name: 'reset-password-form', component: ResetPasswordForm, meta: { auth:false } } ... ]
Create Forget Password Reset Link From
As per the first route, I’m creating a component “ForgotPassword.vue” at “resources/js/page” directory. In this component, we create a form where the user fills there registered email id and request the reset link.
<template> <div class="container"> <div class="row justify-content-center"> <div class="col-6"> <div class="card card-default"> <div class="card-header">Reset Password</div> <div class="card-body"> <form autocomplete="off" @submit.prevent="requestResetPassword" method="post"> <div class="form-group"> <label for="email">E-mail</label> <input type="email" id="email" class="form-control" placeholder="user@example.com" v-model="email" required> </div> <button type="submit" class="btn btn-primary">Send Password Reset Link</button> </form> </div> </div> </div> </div> </div> </template> <script> export default { data() { return { email: null, has_error: false } }, methods: { requestResetPassword() { this.$http.post("/auth/reset-password", {email: this.email}).then(result => { this.response = result.data; console.log(result.data); }, error => { console.error(error); }); } } } </script>
In the above ForgotPassword.vue component, I’m using the API which sends an email to the users who want to reset the password. The user needs to click on the link which redirects a user to our second route. Where the user has to enter the new password for reset.
I’m using mailtrap to test email notifications. It’s easy to add in your Laravel application. You just need to create an account on mailtrap then add your mailtrap credentials in your “.env” file. After this, you will receive all your emails on your mailtrap inbox.
You can learn more on Laravel Mailable here.
As per the screenshot, when you click on the Reset Password button then user redirect to our application where he/she able to reset there password.
Create Forget Password Request Form
As per the second route, I’m creating a component “ResetPasswordForm.vue” at “resources/js/page” directory. In this component, we create a form where the user fills there new password then submit the form.
<template> <div class="container"> <div class="row justify-content-center"> <div class="col-6"> <div class="card card-default"> <div class="card-header">New Password</div> <div class="card-body"> <!-- <ul v-if="errors"> <li v-for="error in errors" v-bind:key="error">{{ msg }}</li> </ul> --> <form autocomplete="off" @submit.prevent="resetPassword" method="post"> <div class="form-group"> <label for="email">E-mail</label> <input type="email" id="email" class="form-control" placeholder="user@example.com" v-model="email" required> </div> <div class="form-group"> <label for="email">Password</label> <input type="password" id="password" class="form-control" placeholder="" v-model="password" required> </div> <div class="form-group"> <label for="email">Confirm Password</label> <input type="password" id="password_confirmation" class="form-control" placeholder="" v-model="password_confirmation" required> </div> <button type="submit" class="btn btn-primary">Update</button> </form> </div> </div> </div> </div> </div> </template> <script> export default { data() { return { token: null, email: null, password: null, password_confirmation: null, has_error: false } }, methods: { resetPassword() { this.$http.post("/auth/reset/password/", { token: this.$route.params.token, email: this.email, password: this.password, password_confirmation: this.password_confirmation }) .then(result => { // console.log(result.data); this.$router.push({name: 'login'}) }, error => { console.error(error); }); } } } </script>
As per our email notification mail, you see URL contains the unique token. And we send this token with our form parameters to the server using API. After that our API handle this request and update the user password.
Conclusion
In this article, we are discussing “Vue Js Reset Password With Laravel API”. I’m trying to explain each of the steps which require to implements Reset Password feature in Vue Laravel application. Hope this article will helps you in your development. We will discuss more on Laravel and Vue Js in our future articles. Please feel free to add comments if any query or you can send your feedback 😉
If you like our content, please consider buying us a coffee.
Thank you for your support!
Buy Me a Coffee
Hi, this article was very helpful to implement it in my project, thanks you!.
In my case I had a problem with the following functions in AuthController:
protected function sendResetLinkResponse(Request $request, $response)
protected function sendResetResponse(Request $request, $response)
The problem was caused by the first parameter, which the original functions did require, only the string $response variable, so I changed them to:
protected function sendResetLinkResponse($response)
protected function sendResetResponse($response)
And then I was able to get the JSON response correctly.
Also I assigned a name to the Route ->name(‘password.reset’), because I was getting a Route not found error.
I hope this helps someone with the sames issues.
Thanks again, I will be looking forward for your next article.
Great tutorial. This was a big help.
There’s a problem with the trait’s methods “broker”, the thing is that it is implemented on both traits, so the Controller doesn’t know which to call, on what moment.
The error dropped is the following: “Trait method broker has not been applied, because there are collisions with other trait methods on App\\Http\\Controllers\\API\\AuthController”
I tried adding the traits as:
“`
use SendsPasswordResetEmails, ResetsPasswords {
SendsPasswordResetEmails::broker insteadof ResetsPasswords;
}
“`
But now it drops the error:
“message”: “Undefined index: password”
on file
“\\vendor\\laravel\\framework\\src\\Illuminate\\Auth\\Passwords\\PasswordBroker.php”
Try using this instead:
“`
use SendsPasswordResetEmails, ResetsPasswords {
SendsPasswordResetEmails::broker insteadof ResetsPasswords;
ResetsPasswords::credentials insteadof SendsPasswordResetEmails;
}
“`
Does anyone know how to solve this error?
in authcontroller.php , inside the class, you have to add the use:
class AuthController extends Controller {
use SendsPasswordResetEmails;
use ResetsPasswords
Yep
“`
class AuthController extends Controller
{
use SendsPasswordResetEmails, ResetsPasswords {
SendsPasswordResetEmails::broker insteadof ResetsPasswords;
ResetsPasswords::credentials insteadof SendsPasswordResetEmails;
}
“`
Which route did you give the name? I have the same name error…
can i ask help here? After i do the guide, i have an error and it says “”Too few arguments to function App\Http\Controllers\API\AuthController::callResetPassword(), 0 passed and exactly 2 expected””. what should i do?
It seems I needed to add the semi-colon here:
parent::__construct($token);
Thanks! Great post! It was really helpful.
Getting this error even after trying the solutions above.
{message: “Trait ‘Illuminate\Foundation\Auth\SendsPasswordResetEmails’ not found”,…}
message: “Trait ‘Illuminate\Foundation\Auth\SendsPasswordResetEmails’ not found”
exception: “Symfony\Component\ErrorHandler\Error\FatalError
please help
Did you solve the issue? I have the exact same error.
How come you don’t fetch the email from the url?…how do you get the mail and verify with the token, this is the correctmail to be updated..
My question is Mr x could update the email of Mr y using the link
I get this error
App\Http\Controllers\AuthController::sendResetLinkEmail does not exist
maybe I don’t understand something. Can you help me?
Thank you in advance
you need to call the trait in your controller
use SendsPasswordResetEmails;
i’m getting this type of password reset link so i’m geeting error like The GET method is not supported for this route. Supported methods: POST.
use SendsPasswordResetEmails; use but not working
Thank you,
You saved me so much time!
fail to send the email
The POST method is not supported for this route. Supported methods: GET, HEAD.
I’m facing this problem.
Anyone can you help me please?