Files
habitica/website/server/controllers/top-level/auth.js
Matteo Pagliazzi d30e7b9251 Don't send plaintext reset passwords via email (#8457)
* start work to avoid sending reset password in plaintext via email

* start checking parameters

* fix new password reset email

* render error if password reset code is missing or invalid

* implement POST route, conversion to bcrypt and messages

* add auth.local.passwordResetCode field

* add failing tests, move reset code validation func to lib, fixes, remove old tests

* fix unit tests

* fix page rendering and add integration tests

* fix password reset page

* add integration test

* fix string

* fix tests url
2017-02-14 18:08:31 +01:00

99 lines
2.7 KiB
JavaScript

import locals from '../../middlewares/locals';
import { validatePasswordResetCodeAndFindUser, convertToBcrypt} from '../../libs/password';
let api = {};
// Internal authentication routes
function renderPasswordResetPage (options = {}) {
// res is express' res, error any error and success if the password was successfully changed
let {res, hasError, success = false, message} = options;
return res.status(hasError ? 401 : 200).render('auth/reset-password-set-new-one.jade', {
env: res.locals.habitrpg,
success,
hasError,
message, // can be error or success message
});
}
// Set a new password after having requested a password reset (GET route to input password)
api.resetPasswordSetNewOne = {
method: 'GET',
url: '/static/user/auth/local/reset-password-set-new-one',
middlewares: [locals],
runCron: false,
async handler (req, res) {
let user = await validatePasswordResetCodeAndFindUser(req.query.code);
let isValidCode = Boolean(user);
return renderPasswordResetPage({
res,
hasError: !isValidCode,
message: !isValidCode ? res.t('invalidPasswordResetCode') : null,
});
},
};
// Set a new password after having requested a password reset (POST route to save password)
api.resetPasswordSetNewOneSubmit = {
method: 'POST',
url: '/static/user/auth/local/reset-password-set-new-one',
middlewares: [locals],
runCron: false,
async handler (req, res) {
let user = await validatePasswordResetCodeAndFindUser(req.query.code);
let isValidCode = Boolean(user);
if (!isValidCode) return renderPasswordResetPage({
res,
hasError: true,
message: res.t('invalidPasswordResetCode'),
});
let newPassword = req.body.newPassword;
let confirmPassword = req.body.confirmPassword;
if (!newPassword) {
return renderPasswordResetPage({
res,
hasError: true,
message: res.t('missingNewPassword'),
});
}
if (newPassword !== confirmPassword) {
return renderPasswordResetPage({
res,
hasError: true,
message: res.t('passwordConfirmationMatch'),
});
}
// set new password and make sure it's using bcrypt for hashing
await convertToBcrypt(user, String(newPassword));
user.auth.local.passwordResetCode = undefined; // Reset saved password reset code
await user.save();
return renderPasswordResetPage({
res,
hasError: false,
success: true,
message: res.t('passwordChangeSuccess'),
});
},
};
// Logout the user from the website.
api.logout = {
method: 'GET',
url: '/logout',
async handler (req, res) {
if (req.logout) req.logout(); // passportjs method
req.session = null;
res.redirect('/');
},
};
module.exports = api;