Skip to content

Instantly share code, notes, and snippets.

@JohnnyWalkerDigital
Last active July 2, 2025 18:55
Show Gist options
  • Select an option

  • Save JohnnyWalkerDigital/ce0fede18f8dadecd557341a36b94f8a to your computer and use it in GitHub Desktop.

Select an option

Save JohnnyWalkerDigital/ce0fede18f8dadecd557341a36b94f8a to your computer and use it in GitHub Desktop.

Revisions

  1. JohnnyWalkerDigital revised this gist Nov 20, 2019. No changes.
  2. JohnnyWalkerDigital revised this gist Nov 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion laravel-password-reset.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    Here's how to overcome this common gotcha: The default password reset system not working out of the box with Laravel 5.x (as you're not sent the user's password), without having to alter altering vendor/core.
    Here's how to overcome this common gotcha: The default password reset system not working out of the box with Laravel 5.x (as you're not sent the user's password), without having to alter altering vendor/core. Here's how to make it work as you'd expect it to without changing any vendor files.

    ## 1. Create own notification

  3. JohnnyWalkerDigital created this gist Jun 22, 2018.
    102 changes: 102 additions & 0 deletions laravel-password-reset.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    Here's how to overcome this common gotcha: The default password reset system not working out of the box with Laravel 5.x (as you're not sent the user's password), without having to alter altering vendor/core.

    ## 1. Create own notification

    Firstly create a new notification for your app:

    `php artisan make:notification ResetPassword`

    Then open the newly created file: `app\Notifications\ResetPassword.php` and make the following changes:

    Add `public $token;` to the beginning of the class (ie. after `use Queueable`).

    Add `$this->token = $token;` to the body of your `__construct()` method.

    Add `$token` as parameter to the `__construct()` method (so it reads `__construct($token)`).

    Add the following to the body of your `toMail()` method (replacing what's there by default):

    ```
    return (new MailMessage)
    ->line('You are receiving this email because we received a password reset request for your account.')
    ->action('Reset Password', url(config('app.url').route('password.reset', [$this->token, $notifiable->email], false)))
    ->line('If you did not request a password reset, no further action is required.');
    ```

    What you've done is create a copy of the original vendor/core version of the ResetPassword notification (found in `/vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php`). This allows you to make customisations to it without changing the core Laravel files.

    (One difference we've made is adding `$notifiable->email` to the body of the email.)

    ## 2. Point to your notification

    Now we need to tell Laravel to call our notification instead of the one found in the `CanResetPassword` trait. To do this, just edit your `App/User.php` model:

    Add `use App\Notifications\ResetPassword;` to the top of the file (ie. a link to the notification you just created) and then add a new method:

    ```
    public function sendPasswordResetNotification($token)
    {
    $this->notify(new ResetPassword($token));
    }
    ```

    ## 3. Update your routes

    Finally we need to update our routes to include the new `{email}` parameter:

    `Route::get('/password/reset/{token}/{email}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');`

    Now if the user fills in the `/password/reset` form, they will be sent your notification, with the additional email parameter.

    This now works perfectly!

    ## Additional: Handle errors

    You can improve on the above by adding a bit of error handling. To do this, just pass the email to your form, to handle things if there's a problem:

    Add the following method to `Auth/ForgotPasswordController.php`:

    ```
    protected function sendResetLinkFailedResponse(Request $request, $response)
    {
    return back()->withErrors(
    ['email' => trans($response)]
    )->withInput($request->only('email'));
    }
    ```

    And then place the following at the top: `use Illuminate\Http\Request;`.

    And you're done!

    ## Additional: Finesse the UX

    If you want, I'd also recommend modifying the semantic HTML in your views (regardless of your design). Go to `resources/views/auth/passwords/reset.blade.php` and remove the `autofocus` attribute from the email input element, and add `readonly`. (I move the `autofocus` to the first password input element myself.)

    ## Additional: Encrypt the email address in the URL

    You can still tidy things up a bit more by encrypting the email in the URL. This isn't for security, it's to make it look prettier (so to speak) and make it less likely for the user to mess with the URL and break something.

    To do this, just go to the notification we created in step 1 and change `$notifiable->email` to `encrypt($notifiable->email)`.

    Then go to `app/Http/Controllers/Auth/ResetPasswordController.php` and add the following method:

    ```
    public function showResetForm(Request $request, $token = null)
    {
    return view('auth.passwords.reset')->with(
    ['token' => $token, 'email' => decrypt($request->email)]
    );
    }
    ```

    Don't forget to place `use Illuminate\Http\Request;` at the top, too.

    And you're done! (Again.)

    ---

    I've tested all this fully, and it works perfectly, but if you have an issue, let me know.

    Good luck!