Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJenny Swift
21,999 Pointshow to add a condition to Laravel's login
Hi, I am trying to add a custom condition for logging in a user (with Laravel), so that I can prevent a brute force attack. So for example, only letting the user log in if they have less than 3 failed log-in attempts in the last 10 minutes.
I tried adding the following code to AuthController.php (it is a simplified version of the code provided in the docs) to test if it controls who can log in, but it did not work. I'm not sure where I would need to call the function:
public function authenticate()
{
if (Auth::attempt(['email' => 'someone@example.com']))
{
return redirect()->intended('dashboard');
}
}
I would rather not do the authentication manually. Is there a way of using the provided authentication but just adding an extra condition myself, please?
The reason I would rather not do the authentication manually is because I am still new to Laravel and have trouble reading itβs code and so I figure I could mess something up if I tried. But if I had a clear tutorial on how to do it maybe I would do it manually.
I have tried using Laravel Throttle as dawiyo suggested here, but Iβm having trouble getting it to work, and, although I donβt mind using a package, I would really like to know if there is a way I can do it myself without a package.
2 Answers
Petros Sordinas
16,181 PointsJenny,
Although I would recommend you use Laravel Throttle, a quick and dirty way would be the following:
public function authenticate()
{
// Set login attempts and login time
$loginAttempts = 1;
// If session has login attempts, retrieve attempts counter and attempts time
if (Session::has('loginAttempts'))
{
$loginAttempts = Session::get('loginAttempts');
$loginAttemptTime = Session::get('loginAttemptTime');
// If attempts > 3 and time < 10 minutes
if ($loginAttempts > 3 && (time() - $loginAttemptTime <= 600)
{
return redirect()-back()->with('error', 'maximum login attempts reached. Try again in a while');
}
// If time > 10 minutes, reset attempts counter and time in session
if (time() - $loginAttemptTime > 600)
{
Session::put('loginAttempts', 1)
Session::put('loginAttemptTime', time());
}
} else // If no login attempts stored, init login attempts and time
{
Session::put('loginAttempts', $loginAttempts);
Session::put('loginAttemptTime', time())
}
// If auth ok, redirect to restricted area
if (Auth::attempt(['email' => 'someone@example.com']))
{
return redirect()->intended('dashboard');
}
// Increment login attempts
Session::put('loginAttempts', $loginAttempts + 1);
}
I wrote this out of my head without testing it, so it may not work as it is... just giving you an idea.
The idea is that you save the login attempts counter and login attempt time in the session. If the time elapsed is less than 10 mins and the attempt time is > 3, go back with error. If time elapsed is > 10 mins, reset the variables in the session. In any other case, increment the attempt counter.
If your application is fairly large, I would advise against putting this code in the controller and instead refactor it to a class of its own, but that is another topic entirely.
Petros Sordinas
16,181 PointsIf you are worried about brute force attacks of that scale, I would seriously recommend you go with some proven and tested solution :)
You can include the email address in the stored variables and check against that (and time and attempts).
You could also implement the same idea using a database table and including the email with the attempt and attemptTime variables. That would complicate implementation a little bit, but it all depends on what you want to do.
Jenny Swift
21,999 PointsJenny Swift
21,999 PointsHi Petros, thanks so much for taking the time to respond! Is it safe to use a session to do it, though? I thought bots would be able to use many computers and therefore I would need to keep track of login attempts for a specific user's email address in the database so that it wouldn't matter if the failed logins were with multiple computers?
Jenny Swift
21,999 PointsJenny Swift
21,999 PointsAnd would you mind please helping me with Laravel Throttle? I've followed the installation and configuration instructions. But when I try the following example code from the docs (replacing 'foo' with my own path, and using smaller numbers for the throttle parameters), it doesn't seem to work:
I have also tried this other example from the docs, and each time I refresh the page, count($throttler) is still 1:
I'm assuming $thottler is a typo in the example and should be $throttler.
I figure count($throttler) should increment each time I load the page? But I'm not sure how to get it to do that.