From 63f1e02b74f7b39681c4a7ea1d5ab9695c8ab64b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 03:28:03 +0000 Subject: [PATCH] fix: prevent aggressive session flushing during impersonation and unimpersonation Removes `Session::invalidate()`, `Session::regenerateToken()`, and `Session::flush()` from `logoutAndDestroySession` in `PossessionManager`. These methods were aggressively destroying all application session state (like shopping carts) instead of just managing the authentication status. This ensures standard application states remain intact while using the impersonation feature. Co-authored-by: insign <1113045+insign@users.noreply.github.com> --- src/PossessionManager.php | 4 -- tests/SessionFlushTest.php | 100 +++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 tests/SessionFlushTest.php diff --git a/src/PossessionManager.php b/src/PossessionManager.php index 485ae49..e8f0727 100644 --- a/src/PossessionManager.php +++ b/src/PossessionManager.php @@ -95,9 +95,5 @@ protected function logoutAndDestroySession ( $guard = null ): void } else { Auth::logout(); } - - Session::invalidate(); - Session::regenerateToken(); - Session::flush(); } } diff --git a/tests/SessionFlushTest.php b/tests/SessionFlushTest.php new file mode 100644 index 0000000..5757e2a --- /dev/null +++ b/tests/SessionFlushTest.php @@ -0,0 +1,100 @@ +id(); + $table->string('name'); + $table->string('email')->unique(); + $table->string('password'); + $table->timestamps(); + }); + + Config::set('auth.providers.users.model', SessionFlushAdminStub::class); + } + + public function test_it_preserves_unrelated_session_state_when_impersonating() + { + $admin = SessionFlushAdminStub::create([ + 'name' => 'Admin', + 'email' => 'admin@example.com', + 'password' => bcrypt('password'), + ]); + + $user = SessionFlushUserStub::create([ + 'name' => 'User', + 'email' => 'user@example.com', + 'password' => bcrypt('password'), + ]); + + $this->actingAs($admin, config('possession.admin_guard')); + + // Set an unrelated application session state + Session::put('shopping_cart', ['item_1', 'item_2']); + + Possession::possess($user); + + // Assert session state is preserved + $this->assertTrue(Session::has('shopping_cart')); + $this->assertEquals(['item_1', 'item_2'], Session::get('shopping_cart')); + } + + public function test_it_preserves_unrelated_session_state_when_unimpersonating() + { + $admin = SessionFlushAdminStub::create([ + 'name' => 'Admin', + 'email' => 'admin@example.com', + 'password' => bcrypt('password'), + ]); + + $user = SessionFlushUserStub::create([ + 'name' => 'User', + 'email' => 'user@example.com', + 'password' => bcrypt('password'), + ]); + + $this->actingAs($admin, config('possession.admin_guard')); + + Possession::possess($user); + + // Set an unrelated application session state during impersonation + Session::put('checkout_step', 2); + + Possession::unpossess(); + + // Assert session state is preserved + $this->assertTrue(Session::has('checkout_step')); + $this->assertEquals(2, Session::get('checkout_step')); + } +} + +class SessionFlushAdminStub extends Authenticatable +{ + use ImpersonatesUsers; + protected $table = 'users'; + protected $guarded = []; + public function canPossess(): bool { return true; } +} + +class SessionFlushUserStub extends Authenticatable +{ + use ImpersonatesUsers; + protected $table = 'users'; + protected $guarded = []; + public function canBePossessed(): bool { return true; } +}