Skip to content

Commit 44e2088

Browse files
committed
Adding some more cleanup and refactor
1 parent 82407a9 commit 44e2088

File tree

4 files changed

+108
-40
lines changed

4 files changed

+108
-40
lines changed

app/Http/Controllers/Auth/TwoFactorAuthenticatedSessionController.php

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ class TwoFactorAuthenticatedSessionController extends Controller
2121
*/
2222
public function create(Request $request)
2323
{
24-
if (! $request->session()->has('login.id')) {
25-
return redirect()->route('login');
26-
}
27-
24+
// Session check is now handled by the EnsureTwoFactorChallengeSession middleware
2825
return Inertia::render('auth/two-factor-challenge');
2926
}
3027

@@ -41,49 +38,75 @@ public function store(Request $request)
4138
'recovery_code' => 'nullable|string',
4239
]);
4340

44-
$userId = $request->session()->get('login.id');
45-
$user = User::find($userId);
46-
47-
if (! $user) {
48-
return redirect()->route('login');
49-
}
41+
// If we made it here, user is available via the EnsureTwoFactorChallengeSession middleware
42+
$user = $request->two_factor_auth_user;
5043

51-
// Handle TOTP code
44+
// Handle one-time password (OTP) code
5245
if ($request->filled('code')) {
53-
$secret = decrypt($user->two_factor_secret);
54-
$valid = app(\App\Actions\TwoFactorAuth\VerifyTwoFactorCode::class)($secret, $request->code);
55-
if ($valid) {
56-
app(CompleteTwoFactorAuthentication::class)($user);
57-
return redirect()->intended(route('dashboard', absolute: false));
58-
}
59-
return back()->withErrors(['code' => __('The provided two factor authentication code was invalid.')]);
46+
return $this->authenticateUsingCode($request, $user);
6047
}
6148

6249
// Handle recovery code
6350
if ($request->filled('recovery_code')) {
64-
$recoveryCodes = json_decode(decrypt($user->two_factor_recovery_codes), true);
65-
$provided = $request->recovery_code;
66-
$match = collect($recoveryCodes)->first(function ($code) use ($provided) {
67-
return hash_equals($code, $provided);
68-
});
69-
if (! $match) {
70-
return back()->withErrors(['recovery_code' => __('The provided two factor authentication recovery code was invalid.')]);
71-
}
72-
// Remove used recovery code using the ProcessRecoveryCode action
73-
$updatedCodes = app(ProcessRecoveryCode::class)($recoveryCodes, $match);
74-
if ($updatedCodes === false) {
75-
return back()->withErrors(['recovery_code' => __('The provided two factor authentication recovery code was invalid.')]);
76-
}
77-
$user->two_factor_recovery_codes = encrypt(json_encode($updatedCodes));
78-
$user->save();
79-
// Complete the authentication process
51+
return $this->authenticateUsingRecoveryCode($request, $user);
52+
}
53+
54+
return back()->withErrors(['code' => __('Please provide a valid two factor code.')]);
55+
}
56+
57+
/**
58+
* Authenticate using a one-time password (OTP).
59+
*
60+
* @param \Illuminate\Http\Request $request
61+
* @param \App\Models\User $user
62+
* @return \Illuminate\Http\Response
63+
*/
64+
protected function authenticateUsingCode(Request $request, User $user)
65+
{
66+
$secret = decrypt($user->two_factor_secret);
67+
$valid = app(\App\Actions\TwoFactorAuth\VerifyTwoFactorCode::class)($secret, $request->code);
68+
69+
if ($valid) {
8070
app(CompleteTwoFactorAuthentication::class)($user);
81-
82-
// Redirect to the intended page
8371
return redirect()->intended(route('dashboard', absolute: false));
8472
}
73+
74+
return back()->withErrors(['code' => __('The provided two factor authentication code was invalid.')]);
75+
}
8576

86-
return back()->withErrors(['code' => __('Please provide a valid two factor authentication code.')]);
77+
/**
78+
* Authenticate using a recovery code.
79+
*
80+
* @param \Illuminate\Http\Request $request
81+
* @param \App\Models\User $user
82+
* @return \Illuminate\Http\Response
83+
*/
84+
protected function authenticateUsingRecoveryCode(Request $request, User $user)
85+
{
86+
$recoveryCodes = json_decode(decrypt($user->two_factor_recovery_codes), true);
87+
$provided = $request->recovery_code;
88+
$match = collect($recoveryCodes)->first(function ($code) use ($provided) {
89+
return hash_equals($code, $provided);
90+
});
91+
92+
if (! $match) {
93+
return back()->withErrors(['recovery_code' => __('The provided two factor authentication recovery code was invalid.')]);
94+
}
95+
96+
// Remove used recovery code using the ProcessRecoveryCode action
97+
$updatedCodes = app(ProcessRecoveryCode::class)($recoveryCodes, $match);
98+
if ($updatedCodes === false) {
99+
return back()->withErrors(['recovery_code' => __('The provided two factor authentication recovery code was invalid.')]);
100+
}
101+
102+
$user->two_factor_recovery_codes = encrypt(json_encode($updatedCodes));
103+
$user->save();
104+
105+
// Complete the authentication process
106+
app(CompleteTwoFactorAuthentication::class)($user);
107+
108+
// Redirect to the intended page
109+
return redirect()->intended(route('dashboard', absolute: false));
87110
}
88111
}
89112

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Http\Middleware;
4+
5+
use App\Models\User;
6+
use Closure;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Facades\Auth;
9+
10+
class EnsureTwoFactorChallengeSession
11+
{
12+
/**
13+
* Handle an incoming request.
14+
*
15+
* @param \Illuminate\Http\Request $request
16+
* @param \Closure $next
17+
* @return mixed
18+
*/
19+
public function handle(Request $request, Closure $next)
20+
{
21+
if (! $request->session()->has('login.id')) {
22+
return redirect()->route('login');
23+
}
24+
25+
$userId = $request->session()->get('login.id');
26+
$user = User::find($userId);
27+
28+
if (! $user) {
29+
return redirect()->route('login');
30+
}
31+
32+
// Share the user with the request for controllers to use
33+
$request->merge(['two_factor_auth_user' => $user]);
34+
35+
return $next($request);
36+
}
37+
}

bootstrap/app.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use App\Http\Middleware\EnsureTwoFactorChallengeSession;
34
use App\Http\Middleware\HandleAppearance;
45
use App\Http\Middleware\HandleInertiaRequests;
56
use Illuminate\Foundation\Application;
@@ -14,6 +15,10 @@
1415
health: '/up',
1516
)
1617
->withMiddleware(function (Middleware $middleware) {
18+
$middleware->alias([
19+
'ensure-two-factor-challenge-session' => EnsureTwoFactorChallengeSession::class,
20+
]);
21+
1722
$middleware->encryptCookies(except: ['appearance', 'sidebar_state']);
1823

1924
$middleware->web(append: [

routes/auth.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@
5656
->name('logout');
5757
});
5858

59-
Route::get('two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'create'])
60-
->name('two-factor.challenge');
59+
// Two-factor challenge routes with the ensure-two-factor-challenge-session middleware
60+
Route::middleware('ensure-two-factor-challenge-session')->group(function () {
61+
Route::get('two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'create'])
62+
->name('two-factor.challenge');
6163

62-
Route::post('two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'store']);
64+
Route::post('two-factor-challenge', [TwoFactorAuthenticatedSessionController::class, 'store']);
65+
});

0 commit comments

Comments
 (0)