diff --git a/src/Authentication/Authenticators/Session.php b/src/Authentication/Authenticators/Session.php index ffc54517a..b6f4b6b6d 100644 --- a/src/Authentication/Authenticators/Session.php +++ b/src/Authentication/Authenticators/Session.php @@ -550,6 +550,20 @@ private function checkRememberMeToken(string $remember) */ public function startLogin(User $user): void { + /** @var int|string|null $userId */ + $userId = $this->getSessionKey('id'); + + // Check if already logged in. + if ($userId !== null) { + throw new LogicException( + 'The user has User Info in Session, so already logged in or in pending login state.' + . ' If a logged in user logs in again with other account, the session data of the previous' + . ' user will be used as the new user.' + . ' Fix your code to prevent users from logging in without logging out or delete the session data.' + . ' user_id: ' . $userId + ); + } + $this->user = $user; // Regenerate the session ID to help protect against session fixation diff --git a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php index 171a7e5cf..0c85ba70c 100644 --- a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php @@ -7,6 +7,7 @@ use CodeIgniter\Shield\Authentication\Authenticators\Session; use CodeIgniter\Shield\Config\Auth; use CodeIgniter\Shield\Entities\User; +use CodeIgniter\Shield\Exceptions\LogicException; use CodeIgniter\Shield\Models\RememberModel; use CodeIgniter\Shield\Models\UserModel; use CodeIgniter\Shield\Result; @@ -340,6 +341,26 @@ public function testAttemptSuccess(): void ]); } + public function testAttemptUserHavingSessionDataAttemptsAgain(): void + { + $_SESSION['user']['id'] = '999'; + + $this->expectException(LogicException::class); + $this->expectExceptionMessage( + 'The user has User Info in Session, so already logged in or in pending login state.' + ); + + $this->user->createEmailIdentity([ + 'email' => 'foo@example.com', + 'password' => 'secret123', + ]); + + $this->auth->attempt([ + 'email' => $this->user->email, + 'password' => 'secret123', + ]); + } + public function testAttemptCaseInsensitive(): void { $this->user->createEmailIdentity([