Twofactor authentication and strong password
This commit is contained in:
@@ -15,6 +15,20 @@ $( function () {
|
||||
email : ko.observable(),
|
||||
showPasswordRequest: ko.observable( false ),
|
||||
|
||||
// 2FA properties
|
||||
twoFactorMethod : ko.observable( '' ),
|
||||
twoFactorCode : ko.observable( '' ),
|
||||
twoFactorError : ko.observable( '' ),
|
||||
isVerifying : ko.observable( false ),
|
||||
isResending : ko.observable( false ),
|
||||
|
||||
// Password change properties
|
||||
newPassword : ko.observable( '' ),
|
||||
confirmPassword : ko.observable( '' ),
|
||||
passwordRequirements : ko.observableArray( [] ),
|
||||
passwordChangeError : ko.observable( '' ),
|
||||
isChangingPassword : ko.observable( false ),
|
||||
|
||||
login: function () {
|
||||
dbo.loginService.login();
|
||||
},
|
||||
@@ -26,10 +40,64 @@ $( function () {
|
||||
togglePasswordrequest: function () {
|
||||
var vm = dbo.loginModel
|
||||
vm.showPasswordRequest( !vm.showPasswordRequest() );
|
||||
},
|
||||
|
||||
verifyTwoFactor: function () {
|
||||
dbo.loginService.verifyTwoFactor();
|
||||
},
|
||||
|
||||
resendOtp: function () {
|
||||
dbo.loginService.resendOtp();
|
||||
return false;
|
||||
},
|
||||
|
||||
cancelTwoFactor: function () {
|
||||
$('#twofactor-modal').modal('hide');
|
||||
var vm = dbo.loginModel;
|
||||
vm.twoFactorCode( '' );
|
||||
vm.twoFactorError( '' );
|
||||
vm.twoFactorMethod( '' );
|
||||
},
|
||||
|
||||
handleTwoFactorKeyup: function (data, event) {
|
||||
var vm = dbo.loginModel;
|
||||
// Clear error on input
|
||||
vm.twoFactorError( '' );
|
||||
|
||||
// Only allow digits
|
||||
var sanitized = vm.twoFactorCode().replace(/[^0-9]/g, '');
|
||||
if (sanitized !== vm.twoFactorCode()) {
|
||||
vm.twoFactorCode(sanitized);
|
||||
}
|
||||
|
||||
// Auto-submit on Enter key when code is 6 digits
|
||||
if (vm.twoFactorCode().length === 6 && event.keyCode === 13) {
|
||||
vm.verifyTwoFactor();
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
changePassword: function () {
|
||||
dbo.loginService.changePassword();
|
||||
},
|
||||
|
||||
handlePasswordChangeKeyup: function (data, event) {
|
||||
var vm = dbo.loginModel;
|
||||
// Clear error on input
|
||||
vm.passwordChangeError( '' );
|
||||
|
||||
// Auto-submit on Enter key
|
||||
if (event.keyCode === 13 && vm.newPassword().length >= 8 && vm.confirmPassword().length >= 8) {
|
||||
vm.changePassword();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ko.applyBindings( dbo.loginModel, document.getElementById( "login-form" ) );
|
||||
ko.applyBindings( dbo.loginModel, document.getElementById( "twofactor-modal" ) );
|
||||
} );
|
||||
|
||||
dbo.loginService = {
|
||||
@@ -43,6 +111,35 @@ dbo.loginService = {
|
||||
if ( ! submitDATA ) return self.notifyWrongPassword();
|
||||
|
||||
ds.login( submitDATA, function ( data ) {
|
||||
// Check if password change is required
|
||||
if ( data && typeof data === 'object' && data.result === 'PASSWORD-CHANGE-REQUIRED' ) {
|
||||
// Show password change modal
|
||||
vm.passwordRequirements( data.requirements || [] );
|
||||
vm.newPassword( '' );
|
||||
vm.confirmPassword( '' );
|
||||
vm.passwordChangeError( '' );
|
||||
$('#password-change-modal').modal('show');
|
||||
// Focus on new password input after modal is shown
|
||||
setTimeout(function() {
|
||||
$('#newPassword').focus();
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if 2FA is required
|
||||
if ( data && typeof data === 'object' && data.result === '2FA-REQUIRED' ) {
|
||||
// Show 2FA modal
|
||||
vm.twoFactorMethod( data.method );
|
||||
vm.twoFactorCode( '' );
|
||||
vm.twoFactorError( '' );
|
||||
$('#twofactor-modal').modal('show');
|
||||
// Focus on code input after modal is shown
|
||||
setTimeout(function() {
|
||||
$('#twoFactorCode').focus();
|
||||
}, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( data ) return location.reload();
|
||||
|
||||
self.notifyWrongPassword();
|
||||
@@ -50,6 +147,102 @@ dbo.loginService = {
|
||||
} );
|
||||
},
|
||||
|
||||
verifyTwoFactor: function () {
|
||||
var ds = dbo.loginDataservice;
|
||||
var vm = dbo.loginModel;
|
||||
|
||||
if ( vm.twoFactorCode().length !== 6 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
vm.isVerifying( true );
|
||||
vm.twoFactorError( '' );
|
||||
|
||||
ds.verifyTwoFactor( vm.twoFactorCode(), function ( response ) {
|
||||
vm.isVerifying( false );
|
||||
|
||||
if ( response.success ) {
|
||||
// Close modal and reload page
|
||||
$('#twofactor-modal').modal('hide');
|
||||
location.reload();
|
||||
} else {
|
||||
vm.twoFactorError( response.message || 'Ongeldige verificatiecode' );
|
||||
vm.twoFactorCode( '' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
resendOtp: function () {
|
||||
var ds = dbo.loginDataservice;
|
||||
var vm = dbo.loginModel;
|
||||
|
||||
vm.isResending( true );
|
||||
vm.twoFactorError( '' );
|
||||
|
||||
ds.resendOtp( function ( response ) {
|
||||
vm.isResending( false );
|
||||
|
||||
if ( response.success ) {
|
||||
tellMe( {
|
||||
title : 'Code verzonden',
|
||||
message : response.message || 'Nieuwe code verzonden',
|
||||
modalClass: 'modal-success'
|
||||
} );
|
||||
} else {
|
||||
vm.twoFactorError( response.message || 'Kan code niet opnieuw verzenden' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
changePassword: function () {
|
||||
var ds = dbo.loginDataservice;
|
||||
var vm = dbo.loginModel;
|
||||
|
||||
// Validate passwords match
|
||||
if ( vm.newPassword() !== vm.confirmPassword() ) {
|
||||
vm.passwordChangeError( 'Wachtwoorden komen niet overeen' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate password length
|
||||
if ( vm.newPassword().length < 8 ) {
|
||||
vm.passwordChangeError( 'Wachtwoord moet minimaal 8 karakters bevatten' );
|
||||
return;
|
||||
}
|
||||
|
||||
vm.isChangingPassword( true );
|
||||
vm.passwordChangeError( '' );
|
||||
|
||||
var submitDATA = {
|
||||
new_password: vm.newPassword(),
|
||||
confirm_password: vm.confirmPassword()
|
||||
};
|
||||
|
||||
ds.changePassword( submitDATA, function ( response ) {
|
||||
vm.isChangingPassword( false );
|
||||
|
||||
if ( response.success ) {
|
||||
// Close password change modal
|
||||
$('#password-change-modal').modal('hide');
|
||||
|
||||
// Check if 2FA is required after password change
|
||||
if ( response.result === '2FA-REQUIRED' ) {
|
||||
vm.twoFactorMethod( response.method );
|
||||
vm.twoFactorCode( '' );
|
||||
vm.twoFactorError( '' );
|
||||
$('#twofactor-modal').modal('show');
|
||||
setTimeout(function() {
|
||||
$('#twoFactorCode').focus();
|
||||
}, 500);
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
} else {
|
||||
vm.passwordChangeError( response.message || 'Wachtwoord wijzigen mislukt' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
requestPassword: function () {
|
||||
var ds = dbo.loginDataservice;
|
||||
var self = dbo.loginService;
|
||||
@@ -147,6 +340,24 @@ dbo.loginDataservice = {
|
||||
$.post( 'index.php/login/requestPassword', submitDATA, function ( data ) {
|
||||
callback( data );
|
||||
} );
|
||||
},
|
||||
|
||||
verifyTwoFactor: function ( code, callback ) {
|
||||
$.post( 'index.php/login/verify2fa', { code: code }, function ( data ) {
|
||||
callback( data );
|
||||
} );
|
||||
},
|
||||
|
||||
resendOtp: function ( callback ) {
|
||||
$.post( 'index.php/login/resendOtp', {}, function ( data ) {
|
||||
callback( data );
|
||||
} );
|
||||
},
|
||||
|
||||
changePassword: function ( submitDATA, callback ) {
|
||||
$.post( 'index.php/login/changeWeakPassword', submitDATA, function ( data ) {
|
||||
callback( data );
|
||||
} );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user