Test that password reset links are bound to emails

This adds a test to verify that a password reset link won't work if a user
changed their password after the reset link was sent.

This was reported by a user, but the bug wasn't actually real. But I finished
writing the test, so I thought it's worth committing.
This commit is contained in:
Avital Oliver
2015-06-03 19:49:04 -07:00
parent b3959eac14
commit e2616e8010
3 changed files with 41 additions and 1 deletions

View File

@@ -33,7 +33,7 @@ testAsyncMulti("accounts emails - reset password flow", [
test.equal(result.length, 2); // the first is the email verification
var options = result[1];
var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)")
var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)");
var match = options.text.match(re);
test.isTrue(match);
resetPasswordToken = match[1];

View File

@@ -1033,4 +1033,38 @@ if (Meteor.isServer) (function () {
);
}
);
Tinytest.add(
'passwords - reset password doesn\t work if email changed after email sent',
function (test) {
var username = Random.id();
var email = username + '-intercept@example.com';
var userId = Accounts.createUser({
username: username,
email: email,
password: "old-password"
});
var user = Meteor.users.findOne(userId);
Accounts.sendResetPasswordEmail(userId, email);
var resetPasswordEmailOptions = Meteor.call("getInterceptedEmails", email)[0];
var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)");
var match = resetPasswordEmailOptions.text.match(re);
test.isTrue(match);
var resetPasswordToken = match[1];
var newEmail = Random.id() + '-new@example.com';
Meteor.users.update(userId, {$set: {"emails.0.address": newEmail}});
test.throws(function () {
Meteor.call("resetPassword", resetPasswordToken, "new-password");
}, /Token has invalid email address/);
test.throws(function () {
Meteor.call("login", {user: {username: username}, password: "new-password"});
}, /Incorrect password/);
});
}) ();

View File

@@ -66,6 +66,9 @@ Meteor.methods({
});
Accounts.onLogin(function (attempt) {
if (!attempt.connection) // if login method called from the server
return;
if (capturedLogins[attempt.connection.id])
capturedLogins[attempt.connection.id].push({
successful: true,
@@ -74,6 +77,9 @@ Accounts.onLogin(function (attempt) {
});
Accounts.onLoginFailure(function (attempt) {
if (!attempt.connection) // if login method called from the server
return;
if (capturedLogins[attempt.connection.id]) {
capturedLogins[attempt.connection.id].push({
successful: false,