-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5.4] Crypto-based password resets #17052
Conversation
429b9a5
to
bde653e
Compare
@@ -44,9 +52,12 @@ public function via($notifiable) | |||
*/ | |||
public function toMail($notifiable) | |||
{ | |||
$email = $notifiable->getEmailForPasswordReset(); | |||
$link = url("password/reset?email={$email}&expiration={$this->expiration}&token={$this->token}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sense a hard-coded url...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The URL has always been hard-coded, because Laravel is assuming you're using the Router::auth()
routes.
If you want to use a custom route, you can use your own notification by adding a sendPasswordResetNotification()
method to your class. See CanResetPassword trait.
Personally, I'd prefer it if Laravel were using route names instead of the url()
helper everywhere, but that's a separate PR I recon?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tillkruss, that's a PR i'd love to see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@taylorotwell Are you at all into this idea? Switch all url()
calls with route()
calls?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparing route()
against url()
, the latter is significantly faster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please can you fix up some of the test suite and delete what you want to fix, rather than commenting them out. We have version control if we want them back. :)
$this->assertEquals(PasswordBroker::PASSWORD_RESET, $broker->reset(['password' => 'password', 'token' => 'token'], $callback)); | ||
$this->assertEquals(['user' => $user, 'password' => 'password'], $_SERVER['__password.reset.test']); | ||
} | ||
// public function testGetUserThrowsExceptionIfUserDoesntImplementCanResetPassword() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't comment out tests.
c887124
to
18700c9
Compare
@GrahamCampbell: Sure, just adjusted all the unit tests. |
Pending review from Taylor now. :)
@tillkruss thanks for that, getting rid of |
@lucasmichot: Seemed like the most straight forward approach to me. Do you want make a branch using JWT to see what is looks like? |
* Create a notification instance. | ||
* | ||
* @param string $token | ||
* @return void | ||
*/ | ||
public function __construct($token) | ||
public function __construct($token, $expiration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add also parameter to PHPDoc, it will be @param int $expiration
* @param \Illuminate\Contracts\Auth\UserProvider $users | ||
* @return void | ||
*/ | ||
public function __construct(TokenRepositoryInterface $tokens, | ||
UserProvider $users) | ||
public function __construct($app, UserProvider $users, $expiration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe is also good idea to type hinting here $app
parameter.
$email, | ||
$expiration, | ||
$user->getKey(), | ||
$user->updated_at->timestamp, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about using the updated_at
timestamp in here, an unrelated change to the user model would break an in-progress password reset and cause confusion for the user as to why their reset token was invalid. The password is sufficient to make the token unique and uncrackable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right!
bb10bea
to
af70f3c
Compare
Does this block the ability to use the same reset link twice? It looks like it does with the |
Yes, the link expires when the password hash changes. |
Perfect 👍🏼
|
This will probably have to be re-targeted to 5.5. I just don't have time to look at it for this release cycle. |
Probably fine to keep this open though, and just retarget? |
As discussed with @taylorotwell, a proof-of-concept for crypto-based password resets.
This approach allows us to drop the
password_resets
table and remove theTokenRepositoryInterface
andDatabaseTokenRepository
. Seelaravel/laravel
changes.The email field has been removed from the reset form.
If the reset link is expired/invalid, or the user doesn't exists, then the password reset form is hidden and an appropriate warning message is displayed.