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
@@ -50,6 +50,7 @@ export class Config {
|
||||
this.preventLoginWithUnverifiedEmail = cacheInfo.preventLoginWithUnverifiedEmail;
|
||||
this.emailVerifyTokenValidityDuration = cacheInfo.emailVerifyTokenValidityDuration;
|
||||
this.accountLockout = cacheInfo.accountLockout;
|
||||
this.passwordPolicy = cacheInfo.passwordPolicy;
|
||||
this.appName = cacheInfo.appName;
|
||||
|
||||
this.analyticsController = cacheInfo.analyticsController;
|
||||
@@ -79,7 +80,8 @@ export class Config {
|
||||
expireInactiveSessions,
|
||||
sessionLength,
|
||||
emailVerifyTokenValidityDuration,
|
||||
accountLockout
|
||||
accountLockout,
|
||||
passwordPolicy
|
||||
}) {
|
||||
const emailAdapter = userController.adapter;
|
||||
if (verifyUserEmails) {
|
||||
@@ -88,6 +90,8 @@ export class Config {
|
||||
|
||||
this.validateAccountLockoutPolicy(accountLockout);
|
||||
|
||||
this.validatePasswordPolicy(passwordPolicy);
|
||||
|
||||
if (typeof revokeSessionOnPasswordReset !== 'boolean') {
|
||||
throw 'revokeSessionOnPasswordReset must be a boolean value';
|
||||
}
|
||||
@@ -113,6 +117,35 @@ export class Config {
|
||||
}
|
||||
}
|
||||
|
||||
static validatePasswordPolicy(passwordPolicy) {
|
||||
if (passwordPolicy) {
|
||||
if (passwordPolicy.resetTokenValidityDuration !== undefined && (typeof passwordPolicy.resetTokenValidityDuration !== 'number' || passwordPolicy.resetTokenValidityDuration <= 0)) {
|
||||
throw 'passwordPolicy.resetTokenValidityDuration must be a positive number';
|
||||
}
|
||||
|
||||
if(passwordPolicy.validatorPattern && !(passwordPolicy.validatorPattern instanceof RegExp)) {
|
||||
throw 'passwordPolicy.validatorPattern must be a RegExp.';
|
||||
}
|
||||
|
||||
if(passwordPolicy.validatorCallback && typeof passwordPolicy.validatorCallback !== 'function' ) {
|
||||
throw 'passwordPolicy.validatorCallback must be a function.';
|
||||
}
|
||||
|
||||
if(passwordPolicy.doNotAllowUsername && typeof passwordPolicy.doNotAllowUsername !== 'boolean') {
|
||||
throw 'passwordPolicy.doNotAllowUsername must be a boolean value.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the passwordPolicy.validatorPattern is configured then setup a callback to process the pattern
|
||||
static setupPasswordValidator(passwordPolicy) {
|
||||
if (passwordPolicy && passwordPolicy.validatorPattern) {
|
||||
passwordPolicy.patternValidator = (value) => {
|
||||
return passwordPolicy.validatorPattern.test(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static validateEmailConfiguration({emailAdapter, appName, publicServerURL, emailVerifyTokenValidityDuration}) {
|
||||
if (!emailAdapter) {
|
||||
throw 'An emailAdapter is required for e-mail verification and password resets.';
|
||||
@@ -163,6 +196,14 @@ export class Config {
|
||||
return new Date(now.getTime() + (this.emailVerifyTokenValidityDuration*1000));
|
||||
}
|
||||
|
||||
generatePasswordResetTokenExpiresAt() {
|
||||
if (!this.passwordPolicy || !this.passwordPolicy.resetTokenValidityDuration) {
|
||||
return undefined;
|
||||
}
|
||||
const now = new Date();
|
||||
return new Date(now.getTime() + (this.passwordPolicy.resetTokenValidityDuration * 1000));
|
||||
}
|
||||
|
||||
generateSessionExpiresAt() {
|
||||
if (!this.expireInactiveSessions) {
|
||||
return undefined;
|
||||
|
||||
Reference in New Issue
Block a user