diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php new file mode 100644 index 0000000..339fae7 --- /dev/null +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -0,0 +1,53 @@ +authenticate(); + + $request->session()->regenerate(); + + return redirect()->intended(RouteServiceProvider::HOME); + } + + /** + * Destroy an authenticated session. + * + * @return \Illuminate\Http\RedirectResponse + */ + public function destroy(Request $request) + { + Auth::guard('web')->logout(); + + $request->session()->invalidate(); + + $request->session()->regenerateToken(); + + return redirect('/'); + } +} diff --git a/app/Http/Controllers/LoginController.php b/app/Http/Controllers/LoginController.php deleted file mode 100644 index a24b98a..0000000 --- a/app/Http/Controllers/LoginController.php +++ /dev/null @@ -1,44 +0,0 @@ - ['required', 'string', 'email'], - 'password' => ['required', 'string'], - ]); - - if (Auth::attempt(Request::only('email', 'password'), Request::boolean('remember'))) { - Session::regenerate(); - - return Redirect::intended(); - } - - return Redirect::back()->withErrors([ - 'email' => 'The provided credentials do not match our records.', - ]); - } - - public function destroy() - { - Auth::logout(); - Session::invalidate(); - Session::regenerateToken(); - - return Redirect::to('/'); - } -} diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php new file mode 100644 index 0000000..ca429c6 --- /dev/null +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -0,0 +1,93 @@ + 'required|string|email', + 'password' => 'required|string', + ]; + } + + /** + * Attempt to authenticate the request's credentials. + * + * @return void + * + * @throws \Illuminate\Validation\ValidationException + */ + public function authenticate() + { + $this->ensureIsNotRateLimited(); + + if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { + RateLimiter::hit($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => __('auth.failed'), + ]); + } + + RateLimiter::clear($this->throttleKey()); + } + + /** + * Ensure the login request is not rate limited. + * + * @return void + * + * @throws \Illuminate\Validation\ValidationException + */ + public function ensureIsNotRateLimited() + { + if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + return; + } + + event(new Lockout($this)); + + $seconds = RateLimiter::availableIn($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => trans('auth.throttle', [ + 'seconds' => $seconds, + 'minutes' => ceil($seconds / 60), + ]), + ]); + } + + /** + * Get the rate limiting throttle key for the request. + * + * @return string + */ + public function throttleKey() + { + return Str::lower($this->input('email')).'|'.$this->ip(); + } +} diff --git a/routes/web.php b/routes/web.php index eee55e5..c59b3da 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,9 +1,9 @@ name('login') ->middleware('guest'); -Route::post('login', [LoginController::class, 'store']) +Route::post('login', [AuthenticatedSessionController::class, 'store']) ->name('login.store') ->middleware('guest'); -Route::delete('logout', [LoginController::class, 'destroy']) +Route::delete('logout', [AuthenticatedSessionController::class, 'destroy']) ->name('logout'); // Dashboard