Skip to content
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

Closed
wants to merge 5 commits into from
Closed

Conversation

tillkruss
Copy link
Contributor

@tillkruss tillkruss commented Dec 30, 2016

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 the TokenRepositoryInterface and DatabaseTokenRepository. See laravel/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.

@tillkruss tillkruss force-pushed the passwords branch 5 times, most recently from 429b9a5 to bde653e Compare December 30, 2016 08:11
@GrahamCampbell GrahamCampbell changed the title [5.4] Crypto-based password resets [5.4] [WIP] Crypto-based password resets Dec 30, 2016
@tillkruss tillkruss changed the title [5.4] [WIP] Crypto-based password resets [5.4] Crypto-based password resets Dec 30, 2016
@@ -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}");
Copy link
Contributor

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...

Copy link
Contributor Author

@tillkruss tillkruss Dec 31, 2016

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?

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

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Member

@GrahamCampbell GrahamCampbell left a 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()
Copy link
Member

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.

@tillkruss tillkruss force-pushed the passwords branch 3 times, most recently from c887124 to 18700c9 Compare January 1, 2017 17:29
@tillkruss
Copy link
Contributor Author

@GrahamCampbell: Sure, just adjusted all the unit tests.

@GrahamCampbell GrahamCampbell dismissed their stale review January 1, 2017 22:11

Pending review from Taylor now. :)

@lucasmichot
Copy link
Contributor

lucasmichot commented Jan 4, 2017

@tillkruss thanks for that, getting rid of password_resets is a good idea !
But why re-implementing what a JWT and its reserved claims can already do out of the box ?

@tillkruss
Copy link
Contributor Author

@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)
Copy link
Contributor

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)
Copy link
Contributor

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,
Copy link

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.

Copy link
Contributor Author

@tillkruss tillkruss Jan 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right!

@tillkruss tillkruss force-pushed the passwords branch 2 times, most recently from bb10bea to af70f3c Compare January 8, 2017 15:58
@tomschlick
Copy link
Contributor

Does this block the ability to use the same reset link twice?

It looks like it does with the validateToken() method but I'm just double checking.

@tillkruss
Copy link
Contributor Author

Yes, the link expires when the password hash changes.

@tomschlick
Copy link
Contributor

tomschlick commented Jan 15, 2017 via email

@taylorotwell
Copy link
Member

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.

@GrahamCampbell
Copy link
Member

Probably fine to keep this open though, and just retarget?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants