LT-98: Passwords shall be required to be changed every 90 days
- route to changePassword page if the password is passwordExpirationDays old - passwordExpirationDays property under passwordOptions object sets the time interval when password should be changed (90 days by default)
This commit is contained in:
parent
11e300f013
commit
d19e402847
@ -105,6 +105,10 @@ Template.changePassword.events({
|
|||||||
} else {
|
} else {
|
||||||
// Save the new password
|
// Save the new password
|
||||||
ActiveEntry.insertHashedPassword(confirmPassword);
|
ActiveEntry.insertHashedPassword(confirmPassword);
|
||||||
|
|
||||||
|
// Update password expiration date
|
||||||
|
ActiveEntry.updatePasswordSetDate();
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
ActiveEntry.signOut();
|
ActiveEntry.signOut();
|
||||||
// Go to signIn page for new entry
|
// Go to signIn page for new entry
|
||||||
|
|||||||
@ -28,7 +28,8 @@ if (Meteor.isClient) {
|
|||||||
requireRegexValidation: true,
|
requireRegexValidation: true,
|
||||||
//requireStrongPasswords: false
|
//requireStrongPasswords: false
|
||||||
passwordHistoryCount: 6,
|
passwordHistoryCount: 6,
|
||||||
failedAttemptsLimit: 5
|
failedAttemptsLimit: 5,
|
||||||
|
passwordExpirationDays: 90
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -50,6 +51,18 @@ if (Meteor.isClient) {
|
|||||||
|
|
||||||
ActiveEntry.configure = function (configObject) {
|
ActiveEntry.configure = function (configObject) {
|
||||||
if (Meteor.isClient) {
|
if (Meteor.isClient) {
|
||||||
|
|
||||||
|
// Set passwordOptions if they are not defined
|
||||||
|
if (!configObject.passwordOptions) {
|
||||||
|
configObject.passwordOptions = {
|
||||||
|
showPasswordStrengthIndicator: true,
|
||||||
|
requireRegexValidation: false,
|
||||||
|
//requireStrongPasswords: false
|
||||||
|
passwordHistoryCount: 6,
|
||||||
|
failedAttemptsLimit: 5,
|
||||||
|
passwordExpirationDays: 90
|
||||||
|
}
|
||||||
|
}
|
||||||
Session.set('Photonic.ActiveEntry', configObject);
|
Session.set('Photonic.ActiveEntry', configObject);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -110,45 +123,79 @@ ActiveEntry.verifyFullName = function (fullName) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ActiveEntry.signIn = function (emailValue, passwordValue){
|
ActiveEntry.signIn = function (emailValue, passwordValue){
|
||||||
|
|
||||||
ActiveEntry.verifyPassword(passwordValue);
|
ActiveEntry.verifyPassword(passwordValue);
|
||||||
ActiveEntry.verifyEmail(emailValue);
|
ActiveEntry.verifyEmail(emailValue);
|
||||||
|
|
||||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||||
var failedAttemptsLimit = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.failedAttemptsLimit || 5;
|
var failedAttemptsLimit = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.failedAttemptsLimit || 5;
|
||||||
|
var passwordExpirationDays = ActiveEntryConfig && ActiveEntryConfig.passwordOptions && ActiveEntryConfig.passwordOptions.passwordExpirationDays || 90;
|
||||||
|
|
||||||
Meteor.call("getFailedAttemptsCount", emailValue, function(error, failedAttemptsCount) {
|
// Check account is locked
|
||||||
|
Meteor.call("isAccountLocked", function (error, isAccountLocked) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.warn(error.message);
|
console.warn(error);
|
||||||
} else {
|
} else {
|
||||||
if (failedAttemptsCount != failedAttemptsLimit) {
|
if (isAccountLocked) {
|
||||||
Meteor.loginWithPassword({email: emailValue}, passwordValue, function (error, result) {
|
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||||
if (error) {
|
return;
|
||||||
// Login failed
|
}
|
||||||
Meteor.call("updateFailedAttempts", [emailValue, failedAttemptsLimit], function(error, failedAttemptCount) {
|
|
||||||
|
Meteor.call("getFailedAttemptsCount", emailValue, function(error, failedAttemptsCount) {
|
||||||
|
if (error) {
|
||||||
|
console.warn(error.message);
|
||||||
|
} else {
|
||||||
|
if (failedAttemptsCount != failedAttemptsLimit) {
|
||||||
|
Meteor.loginWithPassword({email: emailValue}, passwordValue, function (error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.warn(error);
|
// Login failed
|
||||||
|
Meteor.call("updateFailedAttempts", [emailValue, failedAttemptsLimit], function(error, failedAttemptCount) {
|
||||||
|
if (error) {
|
||||||
|
console.warn(error);
|
||||||
|
} else {
|
||||||
|
if (failedAttemptCount == failedAttemptsLimit) {
|
||||||
|
ActiveEntry.errorMessages.set('signInError', "Too many failed login attempts. Your account has been locked.");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ActiveEntry.errorMessages.set('signInError', (failedAttemptsLimit - failedAttemptCount) + " attempts remaining.");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (failedAttemptCount == failedAttemptsLimit) {
|
console.log('result', result);
|
||||||
ActiveEntry.errorMessages.set('signInError', "Too many failed login attempts. Your account has been locked.");
|
// Reset failed attempts
|
||||||
|
Meteor.call("resetFailedAttempts", emailValue);
|
||||||
|
|
||||||
} else {
|
// Check password expiration
|
||||||
ActiveEntry.errorMessages.set('signInError', (failedAttemptsLimit - failedAttemptCount) + " attempts remaining.");
|
// if password expired, route to changePassword page
|
||||||
|
Meteor.call("isPasswordExpired", passwordExpirationDays, function(error, isPasswordExpired) {
|
||||||
|
if (error) {
|
||||||
|
console.warn(error);
|
||||||
|
} else {
|
||||||
|
if (isPasswordExpired) {
|
||||||
|
ActiveEntry.errorMessages.set('changePasswordError', 'Your password expired. Please change your password.');
|
||||||
|
Router.go('/changePassword');
|
||||||
|
} else {
|
||||||
|
Router.go(ActiveEntryConfig.signIn.destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('result', result);
|
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
||||||
Meteor.call("resetFailedAttempts", emailValue);
|
|
||||||
Router.go(ActiveEntryConfig.signIn.destination);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
ActiveEntry.errorMessages.set('signInError', "Your account has been locked.");
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ActiveEntry.signUp = function (emailValue, passwordValue, confirmPassword, fullName){
|
ActiveEntry.signUp = function (emailValue, passwordValue, confirmPassword, fullName){
|
||||||
@ -185,7 +232,9 @@ ActiveEntry.signUp = function (emailValue, passwordValue, confirmPassword, fullN
|
|||||||
} else {
|
} else {
|
||||||
// Add password in previous password field
|
// Add password in previous password field
|
||||||
ActiveEntry.insertHashedPassword(passwordValue);
|
ActiveEntry.insertHashedPassword(passwordValue);
|
||||||
ActiveEntry.updatePasswordCreatedDate();
|
|
||||||
|
// Update password set date
|
||||||
|
ActiveEntry.updatePasswordSetDate();
|
||||||
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
var ActiveEntryConfig = Session.get('Photonic.ActiveEntry');
|
||||||
Router.go(ActiveEntryConfig.signUp.destination);
|
Router.go(ActiveEntryConfig.signUp.destination);
|
||||||
}
|
}
|
||||||
@ -213,8 +262,8 @@ ActiveEntry.insertHashedPassword = function(passwordValue) {
|
|||||||
Meteor.call("insertHashedPassword", [new String(passwordValue).hashCode(),passwordHistoryCount]);
|
Meteor.call("insertHashedPassword", [new String(passwordValue).hashCode(),passwordHistoryCount]);
|
||||||
};
|
};
|
||||||
|
|
||||||
ActiveEntry.updatePasswordCreatedDate = function() {
|
ActiveEntry.updatePasswordSetDate = function() {
|
||||||
Meteor.call("updatePasswordCreatedDate");
|
Meteor.call("updatePasswordSetDate");
|
||||||
};
|
};
|
||||||
|
|
||||||
ActiveEntry.signOut = function (){
|
ActiveEntry.signOut = function (){
|
||||||
|
|||||||
@ -68,10 +68,10 @@ Meteor.methods({
|
|||||||
if (failedAttemptCount == failedAttemptsLimit) {
|
if (failedAttemptCount == failedAttemptsLimit) {
|
||||||
return failedAttemptCount;
|
return failedAttemptCount;
|
||||||
} else {
|
} else {
|
||||||
if (failedAttemptCount == 4) {
|
if (failedAttemptCount == (failedAttemptsLimit - 1)) {
|
||||||
// Locked user account
|
// Locked user account
|
||||||
Meteor.users.update({"emails.address": emailAddress}, {$set: {"profile.isLocked": true, failedPasswordAttempts: failedAttemptCount + 1}});
|
Meteor.users.update({"emails.address": emailAddress}, {$set: {"profile.isLocked": true, failedPasswordAttempts: failedAttemptCount + 1}});
|
||||||
} else if (failedAttemptCount < 4) {
|
} else if (failedAttemptCount < (failedAttemptsLimit - 1)) {
|
||||||
Meteor.users.update({"emails.address": emailAddress}, {$set: {failedPasswordAttempts: failedAttemptCount + 1}});
|
Meteor.users.update({"emails.address": emailAddress}, {$set: {failedPasswordAttempts: failedAttemptCount + 1}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,7 +83,29 @@ Meteor.methods({
|
|||||||
Meteor.users.update({"emails.address": emailAddress}, {$set: {failedPasswordAttempts: 0}});
|
Meteor.users.update({"emails.address": emailAddress}, {$set: {failedPasswordAttempts: 0}});
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePasswordCreatedDate: function() {
|
updatePasswordSetDate: function() {
|
||||||
Meteor.users.update({_id: Meteor.userId()}, {$set: {"services.password.createdAt": new Date()}});
|
Meteor.users.update({_id: Meteor.userId()}, {$set: {"services.password.setDate": new Date()}});
|
||||||
|
},
|
||||||
|
|
||||||
|
isPasswordExpired: function(passwordExpirationDays) {
|
||||||
|
var passwordSetDate = Meteor.users.find({_id: Meteor.userId()}).fetch()[0].services.password.setDate;
|
||||||
|
passwordSetDate.setDate(passwordSetDate.getDate() + passwordExpirationDays);
|
||||||
|
|
||||||
|
if (passwordSetDate <= new Date()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
isAccountLocked: function(emailAddress) {
|
||||||
|
// Check if the user actually exists, and if not, stop here
|
||||||
|
var currentUser = Meteor.users.findOne({"emails.address": emailAddress});
|
||||||
|
if (!currentUser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentUser.profile.isLocked || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#entrySignIn.entryPage,
|
#entrySignIn.entryPage,
|
||||||
#entrySignUp.entryPage
|
#entrySignUp.entryPage,
|
||||||
|
#changePassword
|
||||||
.wrapper-auth
|
.wrapper-auth
|
||||||
.title-auth
|
.title-auth
|
||||||
color: white
|
color: white
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user