Skip to content

Commit 2b3f76b

Browse files
Delete existing tokens when user updates password (#598)
This prevents an attacker using an existing password reset link after a user has changed their password. https://community.auth0.com/t/invalidating-password-reset-links-after-password-change/150437?utm_source=chatgpt.com
1 parent f1ad2dd commit 2b3f76b

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/Http/Controllers/PasswordController.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Laravel\Fortify\Http\Controllers;
44

5+
use Illuminate\Contracts\Auth\PasswordBroker;
56
use Illuminate\Http\Request;
67
use Illuminate\Routing\Controller;
8+
use Illuminate\Support\Facades\Password;
79
use Laravel\Fortify\Contracts\PasswordUpdateResponse;
810
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
911
use Laravel\Fortify\Events\PasswordUpdatedViaController;
@@ -21,8 +23,20 @@ public function update(Request $request, UpdatesUserPasswords $updater)
2123
{
2224
$updater->update($request->user(), $request->all());
2325

26+
$this->broker()->deleteToken($request->user());
27+
2428
event(new PasswordUpdatedViaController($request->user()));
2529

2630
return app(PasswordUpdateResponse::class);
2731
}
32+
33+
/**
34+
* Get the broker to be used to delete any existing password reset tokens.
35+
*
36+
* @return \Illuminate\Contracts\Auth\PasswordBroker
37+
*/
38+
protected function broker(): PasswordBroker
39+
{
40+
return Password::broker(config('fortify.passwords'));
41+
}
2842
}

tests/PasswordControllerTest.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
use App\Actions\Fortify\UpdateUserPassword;
66
use Database\Factories\UserFactory;
7+
use Illuminate\Contracts\Auth\PasswordBroker;
78
use Illuminate\Foundation\Testing\RefreshDatabase;
9+
use Illuminate\Support\Facades\Password;
810
use Illuminate\Validation\ValidationException;
911
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
12+
use Mockery;
1013

1114
class PasswordControllerTest extends OrchestraTestCase
1215
{
@@ -16,9 +19,20 @@ public function test_passwords_can_be_updated()
1619
{
1720
$user = UserFactory::new()->create();
1821

22+
Password::shouldReceive('broker')->andReturn($broker = Mockery::mock(PasswordBroker::class));
23+
24+
$broker->shouldReceive('deleteToken')
25+
->once()
26+
->with($user);
27+
1928
$this->mock(UpdatesUserPasswords::class)
20-
->shouldReceive('update')
21-
->once();
29+
->shouldReceive('update')
30+
->once()
31+
->with($user, [
32+
'current_password' => 'password',
33+
'password' => 'new-password',
34+
'password_confirmation' => 'new-password',
35+
]);
2236

2337
$response = $this->withoutExceptionHandling()->actingAs($user)->putJson('/user/password', [
2438
'current_password' => 'password',

0 commit comments

Comments
 (0)