Strict sign in

This commit is contained in:
Mo Bitar
2018-05-20 12:23:09 -05:00
parent d7b9a021a4
commit 367fbeed20
7 changed files with 100 additions and 48 deletions

View File

@@ -286,7 +286,7 @@ angular.module('app')
}) })
} }
} else { } else {
authManager.login(server, email, pw, false, {}, function(response){ authManager.login(server, email, pw, false, false, {}, function(response){
window.location.reload(); window.location.reload();
}) })
} }

View File

@@ -17,10 +17,6 @@ class AccountMenu {
$scope.user = authManager.user; $scope.user = authManager.user;
$scope.server = syncManager.serverURL; $scope.server = syncManager.serverURL;
// $timeout(() => {
// $scope.openPasswordWizard("change-pw");
// }, 0)
$scope.close = function() { $scope.close = function() {
$timeout(() => { $timeout(() => {
$scope.closeFunction()(); $scope.closeFunction()();
@@ -61,10 +57,13 @@ class AccountMenu {
$scope.formData.status = "Generating Login Keys..."; $scope.formData.status = "Generating Login Keys...";
$timeout(function(){ $timeout(function(){
authManager.login($scope.formData.url, $scope.formData.email, $scope.formData.user_password, $scope.formData.ephemeral, extraParams, authManager.login($scope.formData.url, $scope.formData.email, $scope.formData.user_password,
$scope.formData.ephemeral, $scope.formData.strictSignin, extraParams,
(response) => { (response) => {
if(!response || response.error) { if(!response || response.error) {
syncManager.unlockSyncing(); syncManager.unlockSyncing();
$scope.formData.status = null; $scope.formData.status = null;
var error = response ? response.error : {message: "An unknown error occured."} var error = response ? response.error : {message: "An unknown error occured."}

View File

@@ -114,12 +114,15 @@ class PasswordWizard {
$scope.formData.processing = true; $scope.formData.processing = true;
$scope.processPasswordChange((passwordSuccess) => { $scope.processPasswordChange((passwordSuccess) => {
$scope.formData.statusError = $scope.formData.processing = !passwordSuccess; $scope.formData.statusError = !passwordSuccess;
$scope.formData.processing = passwordSuccess;
if(passwordSuccess) { if(passwordSuccess) {
$scope.formData.status = "Encrypting data with new keys..."; $scope.formData.status = "Encrypting data with new keys...";
$scope.resyncData((syncSuccess) => { $scope.resyncData((syncSuccess) => {
$scope.formData.statusError = $scope.formData.processing = !syncSuccess; $scope.formData.statusError = !syncSuccess;
$scope.formData.processing = syncSuccess;
if(syncSuccess) { if(syncSuccess) {
$scope.lockContinue = false; $scope.lockContinue = false;
@@ -173,7 +176,9 @@ class PasswordWizard {
let password = $scope.formData.currentPassword; let password = $scope.formData.currentPassword;
SFJS.crypto.computeEncryptionKeysForUser(password, authParams, (keys) => { SFJS.crypto.computeEncryptionKeysForUser(password, authParams, (keys) => {
let success = keys.mk === authManager.keys().mk; let success = keys.mk === authManager.keys().mk;
if(!success) { if(success) {
this.currentServerPw = keys.pw;
} else {
alert("The current password you entered is not correct. Please try again."); alert("The current password you entered is not correct. Please try again.");
} }
$timeout(() => callback(success)); $timeout(() => callback(success));
@@ -193,22 +198,24 @@ class PasswordWizard {
} }
$scope.processPasswordChange = function(callback) { $scope.processPasswordChange = function(callback) {
let currentPassword = $scope.formData.currentPassword; let newUserPassword = $scope.securityUpdate ? $scope.formData.currentPassword : $scope.formData.newPassword;
let newPass = $scope.securityUpdate ? currentPassword : $scope.formData.newPassword;
// perform a sync beforehand to pull in any last minutes changes before we change the encryption key (and thus cant decrypt new changes) let currentServerPw = this.currentServerPw;
syncManager.sync((response) => {
authManager.changePassword(currentPassword, newPass, (response) => { SFJS.crypto.generateInitialEncryptionKeysForUser(authManager.user.email, newUserPassword, (newKeys, newAuthParams) => {
if(response.error) { // perform a sync beforehand to pull in any last minutes changes before we change the encryption key (and thus cant decrypt new changes)
alert("There was an error changing your password. Please try again."); syncManager.sync((response) => {
$timeout(() => callback(false)); authManager.changePassword(currentServerPw, newKeys, newAuthParams, (response) => {
} else { if(response.error) {
$timeout(() => callback(true)); alert(response.error.message ? response.error.message : "There was an error changing your password. Please try again.");
} $timeout(() => callback(false));
}) } else {
}, null, "submitPasswordChange") $timeout(() => callback(true));
}
})
}, null, "submitPasswordChange")
});
} }
} }
} }

View File

@@ -97,7 +97,19 @@ angular.module('app')
understanding they are signing in with an older version of the protocol, and must upgrade immediately after completing sign in. understanding they are signing in with an older version of the protocol, and must upgrade immediately after completing sign in.
*/ */
this.isProtocolVersionOutdated = function(version) { this.isProtocolVersionOutdated = function(version) {
return ["001"].includes(version); // YYYY-MM-DD
let expirationDates = {
"001" : Date.parse("2018-01-01"),
"002" : Date.parse("2019-06-01"),
}
let date = expirationDates[version];
if(!date) {
// No expiration date, is active version
return false;
}
let expired = new Date() > date;
return expired;
} }
this.supportsPasswordDerivationCost = function(cost) { this.supportsPasswordDerivationCost = function(cost) {
@@ -117,7 +129,7 @@ angular.module('app')
}) })
} }
this.login = function(url, email, password, ephemeral, extraParams, callback) { this.login = function(url, email, password, ephemeral, strictSignin, extraParams, callback) {
this.getAuthParamsForEmail(url, email, extraParams, function(authParams){ this.getAuthParamsForEmail(url, email, extraParams, function(authParams){
// SF3 requires a unique identifier in the auth params // SF3 requires a unique identifier in the auth params
@@ -147,7 +159,7 @@ angular.module('app')
} }
if(this.isProtocolVersionOutdated(authParams.version)) { if(this.isProtocolVersionOutdated(authParams.version)) {
let message = `The encryption version for your account, ${authParams.version}, is outdated. You may proceed with login, but are advised to follow prompts for Security Updates once inside. Please visit standardnotes.org/help/security for more information.\n\nClick 'OK' to proceed with login.` let message = `The encryption version for your account, ${authParams.version}, is outdated and requires upgrade. You may proceed with login, but are advised to follow prompts for Security Updates once inside. Please visit standardnotes.org/help/security for more information.\n\nClick 'OK' to proceed with login.`
if(!confirm(message)) { if(!confirm(message)) {
return; return;
} }
@@ -168,21 +180,30 @@ angular.module('app')
return; return;
} }
if(strictSignin) {
// Refuse sign in if authParams.version is anything but the latest version
var latestVersion = SFJS.crypto.version();
if(authParams.version !== latestVersion) {
let message = `Strict sign in refused server sign in parameters. The latest security version is ${latestVersion}, but your account is reported to have version ${authParams.version}. If you'd like to proceed with sign in anyway, please disable strict sign in and try again.`;
callback({error: {message: message}});
return;
}
}
SFJS.crypto.computeEncryptionKeysForUser(password, authParams, function(keys){ SFJS.crypto.computeEncryptionKeysForUser(password, authParams, function(keys){
console.log("Signing in with params", authParams, keys);
var requestUrl = url + "/auth/sign_in"; var requestUrl = url + "/auth/sign_in";
var params = _.merge({password: keys.pw, email: email}, extraParams); var params = _.merge({password: keys.pw, email: email}, extraParams);
httpManager.postAbsolute(requestUrl, params, function(response){ httpManager.postAbsolute(requestUrl, params, function(response){
this.setEphemeral(ephemeral); this.setEphemeral(ephemeral);
this.handleAuthResponse(response, email, url, authParams, keys); this.handleAuthResponse(response, email, url, authParams, keys);
this.checkForSecurityUpdate(); this.checkForSecurityUpdate();
callback(response); $timeout(() => callback(response));
}.bind(this), function(response){ }.bind(this), function(response){
console.error("Error logging in", response); console.error("Error logging in", response);
if(typeof response !== 'object') { if(typeof response !== 'object') {
response = {error: {message: "A server error occurred while trying to sign in. Please try again."}}; response = {error: {message: "A server error occurred while trying to sign in. Please try again."}};
} }
callback(response); $timeout(() => callback(response));
}) })
}.bind(this)); }.bind(this));
@@ -235,23 +256,21 @@ angular.module('app')
}); });
} }
this.changePassword = function(current_password, new_password, callback) { this.changePassword = function(current_server_pw, newKeys, newAuthParams, callback) {
let email = this.user.email; let email = this.user.email;
SFJS.crypto.generateInitialEncryptionKeysForUser(email, new_password, (keys, authParams) => { let newServerPw = newKeys.pw;
var requestUrl = storageManager.getItem("server") + "/auth/change_pw";
var params = _.merge({current_password: current_password, new_password: keys.pw}, authParams);
httpManager.postAbsolute(requestUrl, params, (response) => { var requestUrl = storageManager.getItem("server") + "/auth/change_pw";
this.handleAuthResponse(response, email, null, authParams, keys); var params = _.merge({new_password: newServerPw}, newAuthParams);
callback(response);
}, (response) => { httpManager.postAbsolute(requestUrl, params, (response) => {
var error = response; this.handleAuthResponse(response, email, null, newAuthParams, newKeys);
if(!error) { callback(response);
error = {message: "Something went wrong while changing your password. Your password was not changed. Please try again."} }, (response) => {
} if(typeof response !== 'object') {
console.error("Change pw error", response); response = {error: {message: "Something went wrong while changing your password. Your password was not changed. Please try again."}}
callback({error: error}); }
}) callback(response);
}) })
} }

View File

@@ -54,7 +54,7 @@
&.small { &.small {
> .content { > .content {
width: 700px; width: 700px;
height: 335px; height: 344px;
} }
} }

View File

@@ -1,5 +1,24 @@
.sn-component { .sn-component {
.notification {
&.unpadded {
padding: 0;
padding-bottom: 0 !important;
padding-top: 0;
}
.padded-row {
padding: 10px 12px;
}
.bordered-row {
border-bottom: 1px solid rgba(black, 0.1);
border-top: 1px solid rgba(black, 0.1);
}
}
} }
.panel { .panel {

View File

@@ -31,10 +31,18 @@
.notification.info{"ng-if" => "formData.showRegister"} .notification.info{"ng-if" => "formData.showRegister"}
%h2.title No Password Reset. %h2.title No Password Reset.
.text Because your notes are encrypted using your password, Standard Notes does not have a password reset option. You cannot forget your password. .text Because your notes are encrypted using your password, Standard Notes does not have a password reset option. You cannot forget your password.
.advanced-options.panel-row{"ng-if" => "formData.showAdvanced"}
.notification.unpadded.default.advanced-options.panel-row{"ng-if" => "formData.showAdvanced"}
.panel-column.stretch .panel-column.stretch
%label Sync Server Domain %h4.title.panel-row.padded-row Advanced Options
%input.form-control.mt-5{:name => 'server', :placeholder => 'Server URL', :required => true, :type => 'text', 'ng-model' => 'formData.url'} %div.bordered-row.padded-row
%label Sync Server Domain
%input.form-control.mt-5{:name => 'server', :placeholder => 'Server URL', :required => true, :type => 'text', 'ng-model' => 'formData.url'}
%label.padded-row{"ng-if" => "formData.showLogin"}
%input{"type" => "checkbox", "ng-model" => "formData.strictSignin"}
Use strict sign in
%span
%a{"href" => "https://standardnotes.org/help/security", "target" => "_blank"} (Learn more)
.button-group.stretch.panel-row.form-submit .button-group.stretch.panel-row.form-submit
%button.button.info.featured{"type" => "submit"} %button.button.info.featured{"type" => "submit"}