diff --git a/src/Auth/Manager.php b/src/Auth/Manager.php index 02935431..bc031037 100644 --- a/src/Auth/Manager.php +++ b/src/Auth/Manager.php @@ -622,11 +622,16 @@ public function id() */ public function once(array $credentials = []) { - $this->useSession = false; + $previousUseSession = $this->useSession; - $user = $this->authenticate($credentials); + $this->useSession = false; - $this->useSession = true; + try { + $user = $this->authenticate($credentials); + } + finally { + $this->useSession = $previousUseSession; + } return !!$user; } diff --git a/tests/Auth/ManagerOnceTest.php b/tests/Auth/ManagerOnceTest.php new file mode 100644 index 00000000..a31c922e --- /dev/null +++ b/tests/Auth/ManagerOnceTest.php @@ -0,0 +1,62 @@ +assertTrue($this->getUseSession($manager)); + + try { + $manager->once(['login' => 'someone', 'password' => 'secret']); + $this->fail('The exception from authenticate() should propagate.'); + } + catch (RuntimeException $ex) { + // Expected. + } + + $this->assertTrue($this->getUseSession($manager)); + } + + public function testOnceRestoresThePreviousValueRatherThanTrue() + { + $manager = ManagerOnceTestThrowingManager::instance(); + (new ReflectionProperty($manager, 'useSession'))->setValue($manager, false); + + try { + $manager->once(['login' => 'someone', 'password' => 'secret']); + } + catch (RuntimeException $ex) { + // Expected. + } + + $this->assertFalse($this->getUseSession($manager)); + } + + protected function getUseSession(AuthManager $manager): bool + { + return (new ReflectionProperty($manager, 'useSession'))->getValue($manager); + } +} + +class ManagerOnceTestThrowingManager extends AuthManager +{ + public function authenticate(array $credentials, $remember = true) + { + throw new RuntimeException('authentication failed'); + } +}