Password requirement custom message (#5399)

* Added validationError(custom message) for Password requirement fail

* Changed validationError from valodationError in README.md
This commit is contained in:
pateldharad
2019-02-28 16:17:31 -05:00
committed by Arthur Cinader
parent 1e7cc7ba00
commit 6eaefd95ae
3 changed files with 24 additions and 7 deletions

View File

@@ -326,8 +326,9 @@ var server = ParseServer({
// If both are specified, both checks must pass to accept the password // If both are specified, both checks must pass to accept the password
// 1. a RegExp object or a regex string representing the pattern to enforce // 1. a RegExp object or a regex string representing the pattern to enforce
validatorPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/, // enforce password with at least 8 char with at least 1 lower case, 1 upper case and 1 digit validatorPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/, // enforce password with at least 8 char with at least 1 lower case, 1 upper case and 1 digit
// 2. a callback function to be invoked to validate the password // 2. a callback function to be invoked to validate the password
validatorCallback: (password) => { return validatePassword(password) }, validatorCallback: (password) => { return validatePassword(password) },
validationError: 'Password must contain at least 1 digit.' // optional error message to be sent instead of the default "Password does not meet the Password Policy requirements." message.
doNotAllowUsername: true, // optional setting to disallow username in passwords doNotAllowUsername: true, // optional setting to disallow username in passwords
maxPasswordAge: 90, // optional setting in days for password expiry. Login fails if user does not reset the password within this period after signup/last reset. maxPasswordAge: 90, // optional setting in days for password expiry. Login fails if user does not reset the password within this period after signup/last reset.
maxPasswordHistory: 5, // optional setting to prevent reuse of previous n passwords. Maximum value that can be specified is 20. Not specifying it or specifying 0 will not enforce history. maxPasswordHistory: 5, // optional setting to prevent reuse of previous n passwords. Maximum value that can be specified is 20. Not specifying it or specifying 0 will not enforce history.

View File

@@ -667,7 +667,7 @@ describe('Password Policy: ', () => {
.then(response => { .then(response => {
expect(response.status).toEqual(302); expect(response.status).toEqual(302);
expect(response.text).toEqual( expect(response.text).toEqual(
`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy` `Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20should%20contain%20at%20least%20one%20digit.&app=passwordPolicy`
); );
Parse.User.logIn('user1', 'has 1 digit') Parse.User.logIn('user1', 'has 1 digit')
@@ -700,6 +700,7 @@ describe('Password Policy: ', () => {
emailAdapter: emailAdapter, emailAdapter: emailAdapter,
passwordPolicy: { passwordPolicy: {
validatorPattern: /[0-9]+/, // password should contain at least one digit validatorPattern: /[0-9]+/, // password should contain at least one digit
validationError: 'Password should contain at least one digit.',
}, },
publicServerURL: 'http://localhost:8378/1', publicServerURL: 'http://localhost:8378/1',
}).then(() => { }).then(() => {
@@ -764,6 +765,9 @@ describe('Password Policy: ', () => {
}) })
.catch(error => { .catch(error => {
expect(error.code).toEqual(142); expect(error.code).toEqual(142);
expect(error.message).toEqual(
'Password cannot contain your username.'
);
done(); done();
}); });
}); });
@@ -853,7 +857,7 @@ describe('Password Policy: ', () => {
.then(response => { .then(response => {
expect(response.status).toEqual(302); expect(response.status).toEqual(302);
expect(response.text).toEqual( expect(response.text).toEqual(
`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20does%20not%20meet%20the%20Password%20Policy%20requirements.&app=passwordPolicy` `Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=Password%20cannot%20contain%20your%20username.&app=passwordPolicy`
); );
Parse.User.logIn('user1', 'r@nd0m') Parse.User.logIn('user1', 'r@nd0m')

View File

@@ -611,8 +611,17 @@ RestWrite.prototype._validatePasswordPolicy = function() {
RestWrite.prototype._validatePasswordRequirements = function() { RestWrite.prototype._validatePasswordRequirements = function() {
// check if the password conforms to the defined password policy if configured // check if the password conforms to the defined password policy if configured
const policyError = // If we specified a custom error in our configuration use it.
'Password does not meet the Password Policy requirements.'; // Example: "Passwords must include a Capital Letter, Lowercase Letter, and a number."
//
// This is especially useful on the generic "password reset" page,
// as it allows the programmer to communicate specific requirements instead of:
// a. making the user guess whats wrong
// b. making a custom password reset page that shows the requirements
const policyError = this.config.passwordPolicy.validationError
? this.config.passwordPolicy.validationError
: 'Password does not meet the Password Policy requirements.';
const containsUsernameError = 'Password cannot contain your username.';
// check whether the password meets the password strength requirements // check whether the password meets the password strength requirements
if ( if (
@@ -632,7 +641,7 @@ RestWrite.prototype._validatePasswordRequirements = function() {
// username is not passed during password reset // username is not passed during password reset
if (this.data.password.indexOf(this.data.username) >= 0) if (this.data.password.indexOf(this.data.username) >= 0)
return Promise.reject( return Promise.reject(
new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError) new Parse.Error(Parse.Error.VALIDATION_ERROR, containsUsernameError)
); );
} else { } else {
// retrieve the User object using objectId during password reset // retrieve the User object using objectId during password reset
@@ -644,7 +653,10 @@ RestWrite.prototype._validatePasswordRequirements = function() {
} }
if (this.data.password.indexOf(results[0].username) >= 0) if (this.data.password.indexOf(results[0].username) >= 0)
return Promise.reject( return Promise.reject(
new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError) new Parse.Error(
Parse.Error.VALIDATION_ERROR,
containsUsernameError
)
); );
return Promise.resolve(); return Promise.resolve();
}); });