diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e4002c478..3f56dcbe5 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -11,6 +11,7 @@ use App\Models\User; use App\Services\PasswordBreachService; use App\Support\Auth\AuthenticatesUsers; use Illuminate\Auth\AuthenticationException; +use Illuminate\Auth\Events\OtherDeviceLogout; use Illuminate\Contracts\Foundation\Application; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -19,6 +20,7 @@ use Illuminate\Support\Arr; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Str; class LoginController extends Controller { @@ -137,6 +139,7 @@ class LoginController extends Controller // Skip 2FA - proceed with login Auth::logoutOtherDevices($request->input('password')); + $this->rotateSessionTokenForCurrentSession($request, $user); $this->clearLoginAttempts($request); // Check for password breach @@ -170,6 +173,7 @@ class LoginController extends Controller } Auth::logoutOtherDevices($request->input('password')); + $this->rotateSessionTokenForCurrentSession($request, $user); $this->clearLoginAttempts($request); // Check for password breach @@ -283,4 +287,16 @@ class LoginController extends Controller return $redirect; } + + private function rotateSessionTokenForCurrentSession(Request $request, User $user): void + { + $newSessionToken = Str::random(60); + + $user->forceFill([ + 'session_token' => $newSessionToken, + ])->save(); + + $request->session()->put('session_token_web', $newSessionToken); + event(new OtherDeviceLogout(Auth::getDefaultDriver(), $user)); + } } diff --git a/app/Http/Controllers/PasswordSecurityController.php b/app/Http/Controllers/PasswordSecurityController.php index 3a021afa1..78eeaa06c 100644 --- a/app/Http/Controllers/PasswordSecurityController.php +++ b/app/Http/Controllers/PasswordSecurityController.php @@ -8,6 +8,7 @@ use App\Http\Requests\Disable2faPasswordSecurityRequest; use App\Models\PasswordSecurity; use App\Models\User; use App\Services\PasswordBreachService; +use Illuminate\Auth\Events\OtherDeviceLogout; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Foundation\Application; @@ -17,6 +18,7 @@ use Illuminate\Routing\Redirector; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Str; use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; use PragmaRX\Google2FA\Exceptions\InvalidCharactersException; use PragmaRX\Google2FA\Exceptions\SecretKeyTooShortException; @@ -196,6 +198,18 @@ class PasswordSecurityController extends Controller // Clean up the temporary session variables $passwordToCheck = $request->session()->get('2fa:password_check'); + + if (is_string($passwordToCheck) && $passwordToCheck !== '') { + Auth::logoutOtherDevices($passwordToCheck); + } + + $newSessionToken = Str::random(60); + $user->forceFill([ + 'session_token' => $newSessionToken, + ])->save(); + $request->session()->put('session_token_web', $newSessionToken); + event(new OtherDeviceLogout(Auth::getDefaultDriver(), $user)); + $request->session()->forget(['2fa:user:id', '2fa:remember', '2fa:password_check']); // Determine where to redirect after successful verification