Adding support for optional Password Policy (#3032)
* adds resetTokenValidityDuration setting * adds a validator to validate password that can be used to enforce strong passwords * adds unit tests for passwordPolicy.validator * adds unit tests to to fail reset password function if password is not in a valid format * updates README.md for passwordPolicy * prevents duplicate check for password validator in updateUserPassword * adds optional setting to disallow username in password * updates test cases to use fdescribe instead of describe * updates test cases to use request-promise instead of request * adds ability to use a RegExp or Callback function or both for a passwordPolicy.validator * expect username parameter in redirect to password_reset_success * adds support for _perishable_token_expires_at in postgres
This commit is contained in:
committed by
Diwakar Cherukumilli
parent
6be9ee5491
commit
cf6ce5b9a3
@@ -368,13 +368,49 @@ RestWrite.prototype.transformUser = function() {
|
||||
if (!this.data.password) {
|
||||
return;
|
||||
}
|
||||
if (this.query && !this.auth.isMaster ) {
|
||||
|
||||
let defer = Promise.resolve();
|
||||
|
||||
// check if the password confirms to the defined password policy if configured
|
||||
if (this.config.passwordPolicy) {
|
||||
const policyError = 'Password does not confirm to the Password Policy.';
|
||||
|
||||
// check whether the password confirms to the policy
|
||||
if (this.config.passwordPolicy.patternValidator && !this.config.passwordPolicy.patternValidator(this.data.password) ||
|
||||
this.config.passwordPolicy.validatorCallback && !this.config.passwordPolicy.validatorCallback(this.data.password)) {
|
||||
return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError));
|
||||
}
|
||||
|
||||
// check whether password contain username
|
||||
if (this.config.passwordPolicy.doNotAllowUsername === true) {
|
||||
if (this.data.username) { // username is not passed during password reset
|
||||
if (this.data.password.indexOf(this.data.username) >= 0)
|
||||
return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError));
|
||||
|
||||
} else { // retrieve the User object using objectId during password reset
|
||||
defer = this.config.database.find('_User', {objectId: this.objectId()})
|
||||
.then(results => {
|
||||
if (results.length != 1) {
|
||||
throw undefined;
|
||||
}
|
||||
if (this.data.password.indexOf(results[0].username) >= 0)
|
||||
return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError));
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.query && !this.auth.isMaster) {
|
||||
this.storage['clearSessions'] = true;
|
||||
this.storage['generateNewSession'] = true;
|
||||
}
|
||||
return passwordCrypto.hash(this.data.password).then((hashedPassword) => {
|
||||
this.data._hashed_password = hashedPassword;
|
||||
delete this.data.password;
|
||||
|
||||
return defer.then(() => {
|
||||
return passwordCrypto.hash(this.data.password).then((hashedPassword) => {
|
||||
this.data._hashed_password = hashedPassword;
|
||||
delete this.data.password;
|
||||
});
|
||||
});
|
||||
|
||||
}).then(() => {
|
||||
|
||||
Reference in New Issue
Block a user