Browse Source

Refactore login controller and add login attempts throttling

Bubka 5 years ago
parent
commit
9f3a770f21

+ 106 - 10
app/Http/Controllers/Auth/LoginController.php

@@ -2,9 +2,15 @@
 
 namespace App\Http\Controllers\Auth;
 
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
 use App\Http\Controllers\Controller;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Lang;
+use Illuminate\Validation\ValidationException;
 use Illuminate\Foundation\Auth\AuthenticatesUsers;
 
+
 class LoginController extends Controller
 {
     /*
@@ -12,28 +18,118 @@ class LoginController extends Controller
     | Login Controller
     |--------------------------------------------------------------------------
     |
-    | This controller handles authenticating users for the application and
-    | redirecting them to your home screen. The controller uses a trait
-    | to conveniently provide its functionality to your applications.
+    | This controller handles authenticating users for the application.
+    | The controller uses a trait to conveniently provide its functionality
+    | to your applications.
     |
     */
 
     use AuthenticatesUsers;
 
     /**
-     * Where to redirect users after login.
+     * Handle a login request to the application.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\JsonResponse
+     *
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function login(Request $request)
+    {
+        $this->validateLogin($request);
+
+        // If the class is using the ThrottlesLogins trait, we can automatically throttle
+        // the login attempts for this application. We'll key this by the username and
+        // the IP address of the client making these requests into this application.
+        if (method_exists($this, 'hasTooManyLoginAttempts') &&
+            $this->hasTooManyLoginAttempts($request)) {
+            $this->fireLockoutEvent($request);
+
+            return $this->sendLockoutResponse($request);
+        }
+
+        if ($this->attemptLogin($request)) {
+            return $this->sendLoginResponse($request);
+        }
+
+        // If the login attempt was unsuccessful we will increment the number of attempts
+        // to login and redirect the user back to the login form. Of course, when this
+        // user surpasses their maximum number of attempts they will get locked out.
+        $this->incrementLoginAttempts($request);
+
+        return $this->sendFailedLoginResponse($request);
+    }
+
+    /**
+     * Send the response after the user was authenticated.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\JsonResponse
+     */
+    protected function sendLoginResponse(Request $request)
+    {
+        $this->clearLoginAttempts($request);
+
+        $success['token'] = $this->guard()->user()->createToken('2FAuth')->accessToken;
+        $success['name'] = $this->guard()->user()->name;
+
+        return response()->json(['message' => $success], Response::HTTP_OK);
+    }
+
+    /**
+     * Get the failed login response instance.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\JsonResponse
+     */
+    protected function sendFailedLoginResponse(Request $request)
+    {
+        return response()->json(['message' => 'unauthorised'], Response::HTTP_UNAUTHORIZED);
+    }
+
+    /**
+     * Redirect the user after determining they are locked out.
      *
-     * @var string
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\JsonResponse
      */
-    protected $redirectTo = '/home';
+    protected function sendLockoutResponse(Request $request)
+    {
+        $seconds = $this->limiter()->availableIn(
+            $this->throttleKey($request)
+        );
+
+        return response()->json(['message' => Lang::get('auth.throttle', ['seconds' => $seconds])], Response::HTTP_TOO_MANY_REQUESTS);
+    }
+
 
     /**
-     * Create a new controller instance.
+     * Validate the user login request.
      *
+     * @param  \Illuminate\Http\Request  $request
      * @return void
+     *
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    protected function validateLogin(Request $request)
+    {
+        $request->validate([
+            $this->username() => 'required|string|exists:users,email',
+            'password' => 'required|string',
+        ]);
+    }
+
+
+    /**
+     * log out current user
+     * @param  Request $request
+     * @return \Illuminate\Http\JsonResponse
      */
-    public function __construct()
+    public function logout(Request $request)
     {
-        $this->middleware('guest')->except('logout');
+        $this->guard()->logout();
+
+        return response()->json(['message' => 'signed out'], Response::HTTP_OK);
     }
-}
+
+}

+ 0 - 41
app/Http/Controllers/UserController.php

@@ -11,47 +11,6 @@ use Illuminate\Support\Facades\Auth;
 class UserController extends Controller
 {
 
-    /**
-     * log a user in
-     * @return [type] [description]
-     */
-    public function login(Request $request)
-    {
-
-        $this->validate($request, [
-            'email' => 'required|exists:users,email',
-            'password' => 'required',
-        ]);
-
-        $credentials = [
-            'email' => request('email'),
-            'password' => request('password')
-        ];
-
-        if (Auth::attempt($credentials)) {
-            $success['token'] = Auth::user()->createToken('MyApp')->accessToken;
-            $success['name'] = Auth::user()->name;
-
-            return response()->json(['message' => $success], 200);
-        }
-
-        return response()->json(['message' => 'unauthorised'], 401);
-    }
-
-
-    /**
-     * log out current user
-     * @param  Request $request
-     * @return json
-     */
-    public function logout()
-    {
-        $accessToken = Auth::user()->token();
-        $accessToken->revoke();
-
-        return response()->json(['message' => 'signed out']);
-    }
-
 
     /**
      * check if a user exists

+ 2 - 0
resources/js/langs/locales.js

@@ -5,6 +5,7 @@ export default {
             "sign_in": "Sign in",
             "register": "Register",
             "hello": "Hi {username} !",
+            "throttle": "Too many login attempts. Please try again in {seconds} seconds.",
             "confirm": {
                 "logout": "Are you sure you want to log out?"
             },
@@ -265,6 +266,7 @@ export default {
             "sign_in": "Se connecter",
             "register": "Créer un compte",
             "hello": "Hi {username} !",
+            "throttle": "Trop de tentatives de connexion. Veuillez réessayer dans {seconds} secondes.",
             "confirm": {
                 "logout": "Etes-vous sûrs de vouloir vous déconnecter ?"
             },

+ 1 - 1
resources/lang/en/auth.php

@@ -17,6 +17,7 @@ return [
     'sign_in' => 'Sign in',
     'register' => 'Register',
     'hello' => 'Hi {username} !',
+    'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
     'confirm' => [
         'logout' => 'Are you sure you want to log out?',
     ],
@@ -45,6 +46,5 @@ return [
         'edit_account' => 'Edit account',
         'profile_saved' => 'Profile successfully updated!'
     ],
-    
 
 ];

+ 1 - 0
resources/lang/fr/auth.php

@@ -17,6 +17,7 @@ return [
     'sign_in' => 'Se connecter',
     'register' => 'Créer un compte',
     'hello' => 'Hi {username} !',
+    'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans :seconds secondes.',
     'confirm' => [
         'logout' => 'Etes-vous sûrs de vouloir vous déconnecter ?',
     ],

+ 3 - 2
routes/api.php

@@ -15,7 +15,8 @@ use Illuminate\Http\Request;
 
 Route::group(['middleware' => 'guest:api'], function () {
 
-    Route::post('login', 'UserController@login');
+    Route::post('login', 'Auth\LoginController@login');
+    
     Route::post('checkuser', 'UserController@checkUser');
     Route::post('register', 'UserController@register');
 
@@ -26,7 +27,7 @@ Route::group(['middleware' => 'guest:api'], function () {
 
 Route::group(['middleware' => 'auth:api'], function() {
 
-    Route::post('logout', 'UserController@logout');
+    Route::post('logout', 'Auth\LoginController@logout');
 
     Route::get('profile/account', 'Profile\AccountController@show');
     Route::patch('profile/account', 'Profile\AccountController@update');