
laravel
🚀
security
🚀
Throttle Password Reset
Laravel Throttle works on failed auth attempts but how about password resets?
Here is what I made my app/Http/Controllers/Auth/PasswordController.php
look like
5.3
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
class PasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords, ThrottlesLogins;
protected $username;
/**
* Create a new password controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Validate the request of sending reset link.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function validateSendResetLinkEmail(Request $request)
{
$this->incrementLoginAttempts($request);
$this->username = 'email';
if($this->hasTooManyLoginAttempts($request)) {
return back()
->withError("You have exceeded the limit of attempts. Please try again shortly")
->withInput();
}
$validator = Validator::make(
$request->all(), [
'email' => 'required|email'
]
);
if ($validator->fails()) {
return back()
->withMessage("If you are in the system you will get an email shortly to reset your password")
->withInput();
}
}
public function loginUsername()
{
return property_exists($this, 'username') ? $this->username : 'email';
}
protected function getThrottleKey(Request $request)
{
return $request->ip();
}
}
5.2
The controller ended up looking like this
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
class PasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords, ThrottlesLogins;
protected $username;
/**
* Create a new password controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Validate the request of sending reset link.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function sendResetLinkEmail(Request $request)
{
$this->incrementLoginAttempts($request);
$this->username = 'email';
Log::debug("Validate");
if($this->hasTooManyLoginAttempts($request)) {
return redirect()->back()->withErrors(['email' => "You have exceeded the limit of attempts. Please try again shortly"]);
}
$this->validate($request, ['email' => 'required|email']);
$broker = $this->getBroker();
$response = Password::broker($broker)->sendResetLink(
$request->only('email'), $this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
public function loginUsername()
{
return property_exists($this, 'username') ? $this->username : 'email';
}
protected function getThrottleKey(Request $request)
{
return $request->ip();
}
}
TIP: While your add it leak even less about your app's user emails
On other thing here is take a moment to change your error message resources/lang/en/passwords.php
'password' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "If you are a user in the system an a reset email has been sent",
Where user
does not leak out any information about the email being correct or not.