From 580fb32724e9dfbeade884dcd91721f4f47b44b5 Mon Sep 17 00:00:00 2001 From: Matthew Boynes Date: Mon, 15 Mar 2021 19:03:48 -0400 Subject: [PATCH 1/5] Require the correct password to rehash it --- src/Illuminate/Auth/SessionGuard.php | 24 ++++++++++++++++--- tests/Integration/Auth/AuthenticationTest.php | 17 ++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index 1f6863141c4c..1748e9af19fb 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 user's password. + * + * @param string $password + * @param string $attribute + * @return bool|null + * + * @throws AuthenticationException If the password is invalid. + */ + 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. * @@ -588,9 +608,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( From ef4541d51a805eb711e14af897515aa7b2ed3569 Mon Sep 17 00:00:00 2001 From: Matthew Boynes Date: Mon, 15 Mar 2021 19:18:55 -0400 Subject: [PATCH 2/5] Add @throws to logoutOtherDevices() --- src/Illuminate/Auth/SessionGuard.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index 1748e9af19fb..ef7ab4ebecc1 100644 --- a/src/Illuminate/Auth/SessionGuard.php +++ b/src/Illuminate/Auth/SessionGuard.php @@ -601,6 +601,8 @@ protected function rehashUserPassword($password, $attribute) * @param string $password * @param string $attribute * @return bool|null + * + * @throws AuthenticationException If the password is invalid. */ public function logoutOtherDevices($password, $attribute = 'password') { From ceb2f46592007ca63bea9836d5547b38c8c47711 Mon Sep 17 00:00:00 2001 From: Matthew Boynes Date: Mon, 15 Mar 2021 21:14:42 -0400 Subject: [PATCH 3/5] Clarify that the current user's password is rehashing --- src/Illuminate/Auth/SessionGuard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index ef7ab4ebecc1..bc6bad4d6a14 100644 --- a/src/Illuminate/Auth/SessionGuard.php +++ b/src/Illuminate/Auth/SessionGuard.php @@ -574,7 +574,7 @@ protected function cycleRememberToken(AuthenticatableContract $user) } /** - * Rehash the user's password. + * Rehash the current user's password. * * @param string $password * @param string $attribute From 7aabd8f0a8f8e0a3420359f807f42ceacb5c4140 Mon Sep 17 00:00:00 2001 From: Matthew Boynes Date: Tue, 16 Mar 2021 07:50:38 -0400 Subject: [PATCH 4/5] Use FQN in docblock, remove description --- src/Illuminate/Auth/SessionGuard.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index bc6bad4d6a14..74569a7bf599 100644 --- a/src/Illuminate/Auth/SessionGuard.php +++ b/src/Illuminate/Auth/SessionGuard.php @@ -580,7 +580,7 @@ protected function cycleRememberToken(AuthenticatableContract $user) * @param string $attribute * @return bool|null * - * @throws AuthenticationException If the password is invalid. + * @throws \Illuminate\Auth\AuthenticationException */ protected function rehashUserPassword($password, $attribute) { @@ -602,7 +602,7 @@ protected function rehashUserPassword($password, $attribute) * @param string $attribute * @return bool|null * - * @throws AuthenticationException If the password is invalid. + * @throws \Illuminate\Auth\AuthenticationException */ public function logoutOtherDevices($password, $attribute = 'password') { From 1e6161250074b8106c1fcf153eeaef7c0bf74c6c Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 16 Mar 2021 09:14:59 -0500 Subject: [PATCH 5/5] formatting --- src/Illuminate/Auth/SessionGuard.php | 41 ++++++++++--------- tests/Integration/Auth/AuthenticationTest.php | 6 +-- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Illuminate/Auth/SessionGuard.php b/src/Illuminate/Auth/SessionGuard.php index 74569a7bf599..48d64c47d39f 100644 --- a/src/Illuminate/Auth/SessionGuard.php +++ b/src/Illuminate/Auth/SessionGuard.php @@ -20,6 +20,7 @@ use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; +use InvalidArgumentException; use RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; @@ -573,26 +574,6 @@ 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. * @@ -622,6 +603,26 @@ public function logoutOtherDevices($password, $attribute = 'password') return $result; } + /** + * Rehash the current user's password. + * + * @param string $password + * @param string $attribute + * @return bool|null + * + * @throws \InvalidArgumentException + */ + protected function rehashUserPassword($password, $attribute) + { + if (! Hash::check($password, $this->user()->{$attribute})) { + throw new InvalidArgumentException("The given password does not match the current password."); + } + + return tap($this->user()->forceFill([ + $attribute => Hash::make($password), + ]))->save(); + } + /** * Register an authentication attempt event listener. * diff --git a/tests/Integration/Auth/AuthenticationTest.php b/tests/Integration/Auth/AuthenticationTest.php index 23862f48d94a..e2ec79050d18 100644 --- a/tests/Integration/Auth/AuthenticationTest.php +++ b/tests/Integration/Auth/AuthenticationTest.php @@ -2,7 +2,6 @@ namespace Illuminate\Tests\Integration\Auth; -use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Auth\Events\Attempting; use Illuminate\Auth\Events\Authenticated; @@ -20,6 +19,7 @@ use Illuminate\Support\Str; use Illuminate\Support\Testing\Fakes\EventFake; use Illuminate\Tests\Integration\Auth\Fixtures\AuthenticationTestUser; +use InvalidArgumentException; use Orchestra\Testbench\TestCase; /** @@ -225,8 +225,8 @@ public function testLoggingOutOtherDevices() public function testPasswordMustBeValidToLogOutOtherDevices() { - $this->expectException(AuthenticationException::class); - $this->expectExceptionMessage('Password mismatch.'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('current password'); $this->app['auth']->loginUsingId(1);