diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 5246ad9..0adea0d 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -30,20 +30,19 @@ class AuthController extends Controller $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], - 'code' => ['nullable', 'digits:6'], ]); $remember = $request->boolean('remember'); - $code = $credentials['code'] ?? null; $authCredentials = Arr::only($credentials, ['email', 'password']); if (Auth::attempt($authCredentials, $remember)) { $user = Auth::user(); if ($user->two_factor_enabled) { - if (!$code || !$this->twoFactor->verifyCode($user->two_factor_secret, $code)) { - Auth::logout(); - return back()->withErrors(['code' => 'Kode 2FA tidak valid atau belum diisi.'])->withInput(); - } + // logout and ask for 2FA challenge + Auth::logout(); + $request->session()->put('2fa:user_id', $user->id); + $request->session()->put('2fa:remember', $remember); + return redirect()->route('twofactor.challenge'); } $request->session()->regenerate(); return redirect()->intended(route('index')); @@ -87,4 +86,46 @@ class AuthController extends Controller return redirect()->route('login'); } + + public function showTwoFactorChallenge(Request $request) + { + if (Auth::check()) { + return redirect()->route('index'); + } + if (!$request->session()->has('2fa:user_id')) { + return redirect()->route('login'); + } + return view('pages.authentication.two-factor-challenge'); + } + + public function verifyTwoFactorChallenge(Request $request): RedirectResponse + { + $data = $request->validate([ + 'code' => ['required', 'digits:6'], + ]); + + $userId = $request->session()->pull('2fa:user_id'); + $remember = $request->session()->pull('2fa:remember', false); + + if (!$userId) { + return redirect()->route('login')->withErrors(['email' => 'Sesi 2FA tidak ditemukan, silakan login kembali.']); + } + + $user = User::find($userId); + if (!$user || !$user->two_factor_enabled || !$user->two_factor_secret) { + return redirect()->route('login')->withErrors(['email' => 'Sesi 2FA tidak valid, silakan login kembali.']); + } + + if (!$this->twoFactor->verifyCode($user->two_factor_secret, $data['code'])) { + // keep session to retry + $request->session()->put('2fa:user_id', $userId); + $request->session()->put('2fa:remember', $remember); + return back()->withErrors(['code' => 'Kode 2FA salah, coba lagi.']); + } + + Auth::login($user, $remember); + $request->session()->regenerate(); + + return redirect()->intended(route('index')); + } } diff --git a/resources/views/pages/authentication/sign-in-cover.blade.php b/resources/views/pages/authentication/sign-in-cover.blade.php index 1f3f82e..9408324 100644 --- a/resources/views/pages/authentication/sign-in-cover.blade.php +++ b/resources/views/pages/authentication/sign-in-cover.blade.php @@ -40,11 +40,6 @@ $bodyClass = 'bg-white'; @error('password') {{ $message }} @enderror -
- - - @error('code') {{ $message }} @enderror -
diff --git a/resources/views/pages/authentication/two-factor-challenge.blade.php b/resources/views/pages/authentication/two-factor-challenge.blade.php new file mode 100644 index 0000000..501e960 --- /dev/null +++ b/resources/views/pages/authentication/two-factor-challenge.blade.php @@ -0,0 +1,55 @@ +@extends('layouts.custom-master') + +@php +$bodyClass = 'bg-white'; +@endphp + +@section('content') +
+
+
+
+
+
+ Verifikasi 2FA +
+

Masukkan kode 2FA

+

Gunakan aplikasi authenticator untuk mendapatkan kode 6 digit.

+
+ @if($errors->any()) +
+
    + @foreach($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif +
+ @csrf +
+ + + @error('code') {{ $message }} @enderror +
+
+ +
+ +
+
+
+
+
+
+ Asset cover +
+

Keamanan Berlapis

+

Lindungi akses dashboard dengan verifikasi dua faktor.

+
+
+
+
+@endsection diff --git a/routes/web.php b/routes/web.php index 2a49b85..1da1f0b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -108,3 +108,5 @@ Route::post('login', [AuthController::class, 'login']); Route::get('register', [AuthController::class, 'showRegister'])->name('register'); Route::post('register', [AuthController::class, 'register']); Route::post('logout', [AuthController::class, 'logout'])->name('logout'); +Route::get('two-factor-challenge', [AuthController::class, 'showTwoFactorChallenge'])->name('twofactor.challenge'); +Route::post('two-factor-challenge', [AuthController::class, 'verifyTwoFactorChallenge'])->name('twofactor.verify');