Share, Read & Learn

Vue Js Reset Password With Laravel API (Part 3)

7 5,124

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.

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.

Vue Js Reset Password With Laravel API

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.

Vue Js Reset Password With Laravel API

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.

Vue Js Reset Password With Laravel API

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 😉

 

Leave A Reply

Your email address will not be published.

7 Comments
  1. Raul Ordonez says

    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.

  2. Aslam Doctor says

    Great tutorial. This was a big help.

  3. ErSoul says

    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”

    1. Shane says

      Try using this instead:

      “`
      use SendsPasswordResetEmails, ResetsPasswords {
      SendsPasswordResetEmails::broker insteadof ResetsPasswords;
      ResetsPasswords::credentials insteadof SendsPasswordResetEmails;
      }
      “`

    2. julian says

      Does anyone know how to solve this error?

      1. manuel says

        in authcontroller.php , inside the class, you have to add the use:

        class AuthController extends Controller {

        use SendsPasswordResetEmails;
        use ResetsPasswords

  4. pj says

    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?