Merge pull request #7166 from shleeable/fix/dangerzone-logout-clear-2fa-session

Invalidate session on DangerZone forced logout to clear 2FA state
pull/7167/head
Shlee 2 weeks ago committed by GitHub
commit 5d38faa257
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -26,9 +26,12 @@ class DangerZone
}
if ($request->session()->get('sudoModeAttempts') > 3) {
$request->session()->pull('redirectNext');
$request->session()->pull('sudoModeAttempts');
// Invalidate the whole session so no security-related flags survive
// the forced logout. Pulling only redirectNext/sudoModeAttempts left
// 2fa.session.active (and sudoMode) intact, which allowed the next
// login on the same session to skip the 2FA checkpoint.
Auth::logout();
$request->session()->invalidate();
return redirect(route('login'));
}

@ -0,0 +1,48 @@
<?php
use App\Http\Middleware\DangerZone;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Http\Request;
use Illuminate\Session\ArraySessionHandler;
use Illuminate\Session\Store;
uses(LazilyRefreshDatabase::class);
/*
|--------------------------------------------------------------------------
| DangerZone forced-logout clears 2FA session state
|--------------------------------------------------------------------------
|
| When a user is logged out for exceeding sudo-mode attempts, the middleware
| must clear security-related session flags. A lingering 2fa.session.active
| would let the next login on the same session skip the 2FA checkpoint.
|
| Note: this middleware class is not currently wired to the `dangerzone`
| alias (which maps to Laravel's RequirePassword), so this exercises the
| class directly to guard its logic should it be reused.
|
*/
it('clears 2fa.session.active when logging out for excessive sudo attempts', function () {
$user = User::factory()->create();
$user->refresh();
$request = Request::create('/settings/email', 'GET');
$session = new Store('test', new ArraySessionHandler(120));
$request->setLaravelSession($session);
$request->setUserResolver(fn () => $user);
$session->put('sudoModeAttempts', 4);
$session->put('2fa.session.active', true);
$session->put('sudoMode', now()->timestamp);
$response = (new DangerZone)->handle($request, function ($req) {
return response('passed-through', 200);
});
expect($response->isRedirect())->toBeTrue();
expect($session->has('2fa.session.active'))->toBeFalse();
expect($session->has('sudoMode'))->toBeFalse();
expect($session->has('sudoModeAttempts'))->toBeFalse();
});
Loading…
Cancel
Save