diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index 1f6863141c4c..74569a7bf599 100644 --- a/src/Illuminate/Auth/SessionGuard.php +++ b/src/Illuminate/Auth/SessionGuard.php @@ -573,6 +573,26 @@ protected function cycleRememberToken(AuthenticatableContract $user) $this->provider->updateRememberToken($user, $token); } + /** + * Rehash the current user's password. + * + * @param string $password + * @param string $attribute + * @return bool|null + * + * @throws \Illuminate\Auth\AuthenticationException + */ + protected function rehashUserPassword($password, $attribute) + { + if (! Hash::check($password, $this->user()->$attribute)) { + throw new AuthenticationException('Password mismatch.'); + } + + return tap($this->user()->forceFill([ + $attribute => Hash::make($password), + ]))->save(); + } + /** * Invalidate other sessions for the current user. * @@ -581,6 +601,8 @@ protected function cycleRememberToken(AuthenticatableContract $user) * @param string $password * @param string $attribute * @return bool|null + * + * @throws \Illuminate\Auth\AuthenticationException */ public function logoutOtherDevices($password, $attribute = 'password') { @@ -588,9 +610,7 @@ public function logoutOtherDevices($password, $attribute = 'password') return; } - $result = tap($this->user()->forceFill([ - $attribute => Hash::make($password), - ]))->save(); + $result = $this->rehashUserPassword($password, $attribute); if ($this->recaller() || $this->getCookieJar()->hasQueued($this->getRecallerName())) { diff --git a/tests/Integration/Auth/AuthenticationTest.php b/tests/Integration/Auth/AuthenticationTest.php index ec23afba3d18..23862f48d94a 100644 --- a/tests/Integration/Auth/AuthenticationTest.php +++ b/tests/Integration/Auth/AuthenticationTest.php @@ -2,6 +2,7 @@ namespace Illuminate\Tests\Integration\Auth; +use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Auth\Events\Attempting; use Illuminate\Auth\Events\Authenticated; @@ -211,7 +212,7 @@ public function testLoggingOutOtherDevices() $this->assertEquals(1, $user->id); - $this->app['auth']->logoutOtherDevices('adifferentpassword'); + $this->app['auth']->logoutOtherDevices('password'); $this->assertEquals(1, $user->id); Event::assertDispatched(OtherDeviceLogout::class, function ($event) { @@ -222,6 +223,20 @@ public function testLoggingOutOtherDevices() }); } + public function testPasswordMustBeValidToLogOutOtherDevices() + { + $this->expectException(AuthenticationException::class); + $this->expectExceptionMessage('Password mismatch.'); + + $this->app['auth']->loginUsingId(1); + + $user = $this->app['auth']->user(); + + $this->assertEquals(1, $user->id); + + $this->app['auth']->logoutOtherDevices('adifferentpassword'); + } + public function testLoggingInOutViaAttemptRemembering() { $this->assertTrue(