diff --git a/src/app/accounts/accountsLoginController.js b/src/app/accounts/accountsLoginController.js index aec7cc68aad..8bcd9063b36 100644 --- a/src/app/accounts/accountsLoginController.js +++ b/src/app/accounts/accountsLoginController.js @@ -149,12 +149,12 @@ angular return; } - var key = cryptoService.makeKey(_masterPassword, _email); - var hash = cryptoService.hashPassword(_masterPassword, key); - apiService.twoFactor.sendEmailLogin({ - email: _email, - masterPasswordHash: hash - }, function () { + return cryptoService.makeKeyAndHash(_email, _masterPassword).then(function (result) { + return apiService.twoFactor.sendEmailLogin({ + email: _email, + masterPasswordHash: result.hash + }).$promise; + }).then(function () { if (doToast) { toastr.success('Verification email sent to ' + $scope.twoFactorEmail + '.'); } diff --git a/src/app/accounts/accountsRecoverController.js b/src/app/accounts/accountsRecoverController.js index d16fba83d19..d5db279e206 100644 --- a/src/app/accounts/accountsRecoverController.js +++ b/src/app/accounts/accountsRecoverController.js @@ -6,17 +6,16 @@ angular $scope.submit = function (model) { var email = model.email.toLowerCase(); - var key = cryptoService.makeKey(model.masterPassword, email); - var request = { - email: email, - masterPasswordHash: cryptoService.hashPassword(model.masterPassword, key), - recoveryCode: model.code.replace(/\s/g, '').toLowerCase() - }; - - $scope.submitPromise = apiService.twoFactor.recover(request, function () { + $scope.submitPromise = cryptoService.makeKeyAndHash(model.email, model.masterPassword).then(function (result) { + return apiService.twoFactor.recover({ + email: email, + masterPasswordHash: result.hash, + recoveryCode: model.code.replace(/\s/g, '').toLowerCase() + }).$promise; + }).then(function () { $analytics.eventTrack('Recovered 2FA'); $scope.success = true; - }).$promise; + }); }; }); diff --git a/src/app/accounts/accountsRegisterController.js b/src/app/accounts/accountsRegisterController.js index 5f3e242e44b..8f317e1cf57 100644 --- a/src/app/accounts/accountsRegisterController.js +++ b/src/app/accounts/accountsRegisterController.js @@ -51,14 +51,17 @@ angular } var email = $scope.model.email.toLowerCase(); - var key = cryptoService.makeKey($scope.model.masterPassword, email); - var encKey = cryptoService.makeEncKey(key); + var makeResult, encKey; - $scope.registerPromise = cryptoService.makeKeyPair(encKey.encKey).then(function (result) { + $scope.registerPromise = cryptoService.makeKeyAndHash(email, $scope.model.masterPassword).then(function (result) { + makeResult = result; + encKey = cryptoService.makeEncKey(result.key); + return cryptoService.makeKeyPair(encKey.encKey); + }).then(function (result) { var request = { name: $scope.model.name, email: email, - masterPasswordHash: cryptoService.hashPassword($scope.model.masterPassword, key), + masterPasswordHash: makeResult.hash, masterPasswordHint: $scope.model.masterPasswordHint, key: encKey.encKeyEnc, keys: { diff --git a/src/app/config.js b/src/app/config.js index 9e37effb96a..a7f5e717172 100644 --- a/src/app/config.js +++ b/src/app/config.js @@ -55,11 +55,14 @@ angular $httpProvider.defaults.headers.post['Content-Type'] = 'text/plain; charset=utf-8'; - if (!$httpProvider.defaults.headers.get) { - $httpProvider.defaults.headers.get = {}; + // stop IE from caching get requests + if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) { + if (!$httpProvider.defaults.headers.get) { + $httpProvider.defaults.headers.get = {}; + } + $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; + $httpProvider.defaults.headers.get['Pragma'] = 'no-cache'; } - $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; - $httpProvider.defaults.headers.get['Pragma'] = 'no-cache'; $httpProvider.interceptors.push('apiInterceptor'); $httpProvider.interceptors.push('jwtInterceptor'); diff --git a/src/app/directives/masterPasswordDirective.js b/src/app/directives/masterPasswordDirective.js index f97386addca..f80d6d7c734 100644 --- a/src/app/directives/masterPasswordDirective.js +++ b/src/app/directives/masterPasswordDirective.js @@ -13,10 +13,11 @@ angular return undefined; } - var key = cryptoService.makeKey(value, profile.email); - var valid = key.keyB64 === cryptoService.getKey().keyB64; - ngModel.$setValidity('masterPassword', valid); - return valid ? value : undefined; + return cryptoService.makeKey(value, profile.email).then(function (result) { + var valid = result.keyB64 === cryptoService.getKey().keyB64; + ngModel.$setValidity('masterPassword', valid); + return valid ? value : undefined; + }); }); // For model -> DOM validation @@ -25,11 +26,11 @@ angular return undefined; } - var key = cryptoService.makeKey(value, profile.email); - var valid = key.keyB64 === cryptoService.getKey().keyB64; - - ngModel.$setValidity('masterPassword', valid); - return value; + return cryptoService.makeKey(value, profile.email).then(function (result) { + var valid = result.keyB64 === cryptoService.getKey().keyB64; + ngModel.$setValidity('masterPassword', valid); + return value; + }); }); }); } diff --git a/src/app/organization/organizationDeleteController.js b/src/app/organization/organizationDeleteController.js index 8075d21ea9e..9ec087814a7 100644 --- a/src/app/organization/organizationDeleteController.js +++ b/src/app/organization/organizationDeleteController.js @@ -5,19 +5,18 @@ authService, toastr, $analytics) { $analytics.eventTrack('organizationDeleteController', { category: 'Modal' }); $scope.submit = function () { - var request = { - masterPasswordHash: cryptoService.hashPassword($scope.masterPassword) - }; - - $scope.submitPromise = apiService.organizations.del({ id: $state.params.orgId }, request, function () { + $scope.submitPromise = cryptoService.hashPassword($scope.masterPassword).then(function (hash) { + return apiService.organizations.del({ id: $state.params.orgId }, { + masterPasswordHash: hash + }).$promise; + }).then(function () { $uibModalInstance.dismiss('cancel'); authService.removeProfileOrganization($state.params.orgId); $analytics.eventTrack('Deleted Organization'); - $state.go('backend.user.vault').then(function () { - toastr.success('This organization and all associated data has been deleted.', - 'Organization Deleted'); - }); - }).$promise; + return $state.go('backend.user.vault'); + }).then(function () { + toastr.success('This organization and all associated data has been deleted.', 'Organization Deleted'); + }); }; $scope.close = function () { diff --git a/src/app/services/authService.js b/src/app/services/authService.js index 79e34d1c7f2..d8bb9be5239 100644 --- a/src/app/services/authService.js +++ b/src/app/services/authService.js @@ -7,48 +7,52 @@ angular _service.logIn = function (email, masterPassword, token, provider, remember) { email = email.toLowerCase(); - var key = cryptoService.makeKey(masterPassword, email); - - var request = { - username: email, - password: cryptoService.hashPassword(masterPassword, key), - grant_type: 'password', - scope: 'api offline_access', - client_id: 'web' - }; - - if (token && typeof (provider) !== 'undefined' && provider !== null) { - remember = remember || remember !== false; - - request.twoFactorToken = token; - request.twoFactorProvider = provider; - request.twoFactorRemember = remember ? '1' : '0'; - } - else if (tokenService.getTwoFactorToken(email)) { - request.twoFactorToken = tokenService.getTwoFactorToken(email); - request.twoFactorProvider = constants.twoFactorProvider.remember; - request.twoFactorRemember = '0'; - } - - // TODO: device information one day? var deferred = $q.defer(); - apiService.identity.token(request).$promise.then(function (response) { + var makeResult; + cryptoService.makeKeyAndHash(email, masterPassword).then(function (result) { + makeResult = result; + + var request = { + username: email, + password: result.hash, + grant_type: 'password', + scope: 'api offline_access', + client_id: 'web' + }; + + // TODO: device information one day? + + if (token && typeof (provider) !== 'undefined' && provider !== null) { + remember = remember || remember !== false; + + request.twoFactorToken = token; + request.twoFactorProvider = provider; + request.twoFactorRemember = remember ? '1' : '0'; + } + else if (tokenService.getTwoFactorToken(email)) { + request.twoFactorToken = tokenService.getTwoFactorToken(email); + request.twoFactorProvider = constants.twoFactorProvider.remember; + request.twoFactorRemember = '0'; + } + + return apiService.identity.token(request).$promise; + }).then(function (response) { if (!response || !response.access_token) { return; } tokenService.setToken(response.access_token); tokenService.setRefreshToken(response.refresh_token); - cryptoService.setKey(key); + cryptoService.setKey(makeResult.key); if (response.TwoFactorToken) { tokenService.setTwoFactorToken(response.TwoFactorToken, email); } if (response.Key) { - cryptoService.setEncKey(response.Key, key); + cryptoService.setEncKey(response.Key, makeResult.key); } if (response.PrivateKey) { diff --git a/src/app/services/cryptoService.js b/src/app/services/cryptoService.js index e8877425c58..81f543f5a78 100644 --- a/src/app/services/cryptoService.js +++ b/src/app/services/cryptoService.js @@ -1,14 +1,16 @@ angular .module('bit.services') - .factory('cryptoService', function ($sessionStorage, constants, $q) { + .factory('cryptoService', function ($sessionStorage, constants, $q, $window) { var _service = {}, _key, _encKey, _legacyEtmKey, _orgKeys, _privateKey, - _publicKey; + _publicKey, + _crypto = $window.crypto, + _subtle = $window.crypto.subtle; _service.setKey = function (key) { _key = key; @@ -233,9 +235,18 @@ angular }; _service.makeKey = function (password, salt) { - var keyBytes = forge.pbkdf2(forge.util.encodeUtf8(password), forge.util.encodeUtf8(salt), - 5000, 256 / 8, 'sha256'); - return new SymmetricCryptoKey(keyBytes); + if (!$window.cryptoShimmed) { + return pbkdf2WC(password, salt, 5000, 256).then(function (keyBuf) { + return new SymmetricCryptoKey(bufToB64(keyBuf), true); + }); + } + else { + var deferred = $q.defer(); + var keyBytes = forge.pbkdf2(forge.util.encodeUtf8(password), forge.util.encodeUtf8(salt), + 5000, 256 / 8, 'sha256'); + deferred.resolve(new SymmetricCryptoKey(keyBytes)); + return deferred.promise; + } }; _service.makeEncKey = function (key) { @@ -290,8 +301,46 @@ angular throw 'Invalid parameters.'; } - var hashBits = forge.pbkdf2(key.key, forge.util.encodeUtf8(password), 1, 256 / 8, 'sha256'); - return forge.util.encode64(hashBits); + if (!$window.cryptoShimmed) { + var keyBuf = key.getBuffers(); + return pbkdf2WC(new Uint8Array(keyBuf.key), password, 1, 256).then(function (hashBuf) { + return bufToB64(hashBuf); + }); + } + else { + var deferred = $q.defer(); + var hashBits = forge.pbkdf2(key.key, forge.util.encodeUtf8(password), 1, 256 / 8, 'sha256'); + deferred.resolve(forge.util.encode64(hashBits)); + return deferred.promise; + } + }; + + function pbkdf2WC(password, salt, iterations, size) { + password = typeof (password) === 'string' ? utf8ToArray(password) : password; + salt = typeof (salt) === 'string' ? utf8ToArray(salt) : salt; + + return _subtle.importKey('raw', password.buffer, { name: 'PBKDF2' }, false, ['deriveKey', 'deriveBits']) + .then(function (importedKey) { + return _subtle.deriveKey( + { name: 'PBKDF2', salt: salt.buffer, iterations: iterations, hash: { name: 'SHA-256' } }, + importedKey, { name: 'AES-CBC', length: size }, true, ['encrypt', 'decrypt']); + }).then(function (derivedKey) { + return _subtle.exportKey('raw', derivedKey); + }); + } + + _service.makeKeyAndHash = function (email, password) { + email = email.toLowerCase(); + var key; + return _service.makeKey(password, email).then(function (theKey) { + key = theKey; + return _service.hashPassword(password, theKey); + }).then(function (theHash) { + return { + key: key, + hash: theHash + }; + }); }; _service.encrypt = function (plainValue, key, plainValueEncoding) { @@ -375,11 +424,11 @@ angular }; var keyBuf = key.getBuffers(); - window.crypto.getRandomValues(obj.iv); + _crypto.getRandomValues(obj.iv); - return window.crypto.subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['encrypt']) + return _subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['encrypt']) .then(function (encKey) { - return window.crypto.subtle.encrypt({ name: 'AES-CBC', iv: obj.iv }, encKey, plainValue); + return _subtle.encrypt({ name: 'AES-CBC', iv: obj.iv }, encKey, plainValue); }).then(function (encValue) { obj.ct = new Uint8Array(encValue); if (!keyBuf.macKey) { @@ -554,7 +603,7 @@ angular var keyBuf = key.getBuffers(), encKey = null; - return window.crypto.subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['decrypt']) + return _subtle.importKey('raw', keyBuf.encKey, { name: 'AES-CBC' }, false, ['decrypt']) .then(function (theEncKey) { encKey = theEncKey; @@ -576,7 +625,7 @@ angular console.error('MAC failed.'); return null; } - return window.crypto.subtle.decrypt({ name: 'AES-CBC', iv: ivBuf }, encKey, ctBuf); + return _subtle.decrypt({ name: 'AES-CBC', iv: ivBuf }, encKey, ctBuf); }); } @@ -663,9 +712,9 @@ angular } function computeMacWC(dataBuf, macKeyBuf) { - return window.crypto.subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']) + return _subtle.importKey('raw', macKeyBuf, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']) .then(function (key) { - return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, key, dataBuf); + return _subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, key, dataBuf); }); } @@ -787,7 +836,7 @@ angular }; function b64ToArray(b64Str) { - var binaryString = window.atob(b64Str); + var binaryString = $window.atob(b64Str); var arr = new Uint8Array(binaryString.length); for (var i = 0; i < binaryString.length; i++) { arr[i] = binaryString.charCodeAt(i); @@ -795,6 +844,24 @@ angular return arr; } + function bufToB64(buf) { + var binary = ''; + var bytes = new Uint8Array(buf); + for (var i = 0; i < bytes.byteLength; i++) { + binary += String.fromCharCode(bytes[i]); + } + return $window.btoa(binary); + } + + function utf8ToArray(str) { + var utf8Str = unescape(encodeURIComponent(str)); + var arr = new Uint8Array(utf8Str.length); + for (var i = 0; i < utf8Str.length; i++) { + arr[i] = utf8Str.charCodeAt(i); + } + return arr; + } + function slice(arr, begin, end) { if (arr.slice) { return arr.slice(begin, end); diff --git a/src/app/settings/settingsChangeEmailController.js b/src/app/settings/settingsChangeEmailController.js index bdea6e9271d..2283c1f07a0 100644 --- a/src/app/settings/settingsChangeEmailController.js +++ b/src/app/settings/settingsChangeEmailController.js @@ -11,22 +11,25 @@ $scope.token = function (model) { _masterPassword = model.masterPassword; - _masterPasswordHash = cryptoService.hashPassword(_masterPassword); _newEmail = model.newEmail.toLowerCase(); - var encKey = cryptoService.getEncKey(); - if (encKey) { - $scope.tokenPromise = requestToken(model); - } - else { - // User is not using an enc key, let's make them one - $scope.tokenPromise = cipherService.updateKey(_masterPasswordHash, function () { - return requestToken(model); - }, processError); - } + cryptoService.hashPassword(_masterPassword).then(function (hash) { + _masterPasswordHash = hash; + + var encKey = cryptoService.getEncKey(); + if (encKey) { + $scope.tokenPromise = requestToken(); + } + else { + // User is not using an enc key, let's make them one + $scope.tokenPromise = cipherService.updateKey(_masterPasswordHash, function () { + return requestToken(); + }, processError); + } + }); }; - function requestToken(model) { + function requestToken() { var request = { newEmail: _newEmail, masterPasswordHash: _masterPasswordHash @@ -40,33 +43,31 @@ $scope.confirm = function (model) { $scope.processing = true; - var newKey = cryptoService.makeKey(_masterPassword, _newEmail); - var encKey = cryptoService.getEncKey(); - var newEncKey = cryptoService.encrypt(encKey.key, newKey, 'raw'); + $scope.confirmPromise = cryptoService.makeKeyAndHash(_newEmail, _masterPassword).then(function (result) { + var encKey = cryptoService.getEncKey(); + var newEncKey = cryptoService.encrypt(encKey.key, result.key, 'raw'); + var request = { + token: model.token, + newEmail: _newEmail, + masterPasswordHash: _masterPasswordHash, + newMasterPasswordHash: result.hash, + key: newEncKey + }; - var request = { - token: model.token, - newEmail: _newEmail, - masterPasswordHash: _masterPasswordHash, - newMasterPasswordHash: cryptoService.hashPassword(_masterPassword, newKey), - key: newEncKey - }; - - $scope.confirmPromise = apiService.accounts.email(request).$promise.then(function () { + return apiService.accounts.email(request).$promise; + }).then(function () { $uibModalInstance.dismiss('cancel'); authService.logOut(); $analytics.eventTrack('Changed Email'); return $state.go('frontend.login.info'); - }, processError).then(function () { + }).then(function () { toastr.success('Please log back in.', 'Email Changed'); - }, processError); + }, function () { + $uibModalInstance.dismiss('cancel'); + toastr.error('Something went wrong. Try again.', 'Oh No!'); + }); }; - function processError() { - $uibModalInstance.dismiss('cancel'); - toastr.error('Something went wrong. Try again.', 'Oh No!'); - } - $scope.close = function () { $uibModalInstance.dismiss('cancel'); }; diff --git a/src/app/settings/settingsChangePasswordController.js b/src/app/settings/settingsChangePasswordController.js index d0bd3ec7896..73355360ea4 100644 --- a/src/app/settings/settingsChangePasswordController.js +++ b/src/app/settings/settingsChangePasswordController.js @@ -31,39 +31,43 @@ } else { // User is not using an enc key, let's make them one - var mpHash = cryptoService.hashPassword(model.masterPassword); - $scope.savePromise = cipherService.updateKey(mpHash, function () { + $scope.savePromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + return cipherService.updateKey(hash); + }, processError).then(function () { return changePassword(model); }, processError); } }; function changePassword(model) { + var makeResult; return authService.getUserProfile().then(function (profile) { - var newKey = cryptoService.makeKey(model.newMasterPassword, profile.email.toLowerCase()); + return cryptoService.makeKeyAndHash(profile.email, model.newMasterPassword); + }).then(function (result) { + makeResult = result; + return cryptoService.hashPassword(model.masterPassword); + }).then(function (hash) { var encKey = cryptoService.getEncKey(); - var newEncKey = cryptoService.encrypt(encKey.key, newKey, 'raw'); + var newEncKey = cryptoService.encrypt(encKey.key, makeResult.key, 'raw'); var request = { - masterPasswordHash: cryptoService.hashPassword(model.masterPassword), - newMasterPasswordHash: cryptoService.hashPassword(model.newMasterPassword, newKey), + masterPasswordHash: hash, + newMasterPasswordHash: makeResult.hash, key: newEncKey }; return apiService.accounts.putPassword(request).$promise; - }, processError).then(function () { + }).then(function () { $uibModalInstance.dismiss('cancel'); authService.logOut(); $analytics.eventTrack('Changed Password'); return $state.go('frontend.login.info'); - }, processError).then(function () { + }).then(function () { toastr.success('Please log back in.', 'Master Password Changed'); - }, processError); - } - - function processError() { - $uibModalInstance.dismiss('cancel'); - toastr.error('Something went wrong.', 'Oh No!'); + }, function () { + $uibModalInstance.dismiss('cancel'); + toastr.error('Something went wrong.', 'Oh No!'); + }); } $scope.close = function () { diff --git a/src/app/settings/settingsDeleteController.js b/src/app/settings/settingsDeleteController.js index 3a057e96b22..15d4c180750 100644 --- a/src/app/settings/settingsDeleteController.js +++ b/src/app/settings/settingsDeleteController.js @@ -5,18 +5,18 @@ authService, toastr, $analytics) { $analytics.eventTrack('settingsDeleteController', { category: 'Modal' }); $scope.submit = function (model) { - var request = { - masterPasswordHash: cryptoService.hashPassword(model.masterPassword) - }; - - $scope.submitPromise = apiService.accounts.postDelete(request, function () { + $scope.submitPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + return apiService.accounts.postDelete({ + masterPasswordHash: hash + }).$promise; + }).then(function () { $uibModalInstance.dismiss('cancel'); authService.logOut(); $analytics.eventTrack('Deleted Account'); - $state.go('frontend.login.info').then(function () { - toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted'); - }); - }).$promise; + return $state.go('frontend.login.info'); + }).then(function () { + toastr.success('Your account has been closed and all associated data has been deleted.', 'Account Deleted'); + }); }; $scope.close = function () { diff --git a/src/app/settings/settingsSessionsController.js b/src/app/settings/settingsSessionsController.js index 493dc1155ff..9f726a505ba 100644 --- a/src/app/settings/settingsSessionsController.js +++ b/src/app/settings/settingsSessionsController.js @@ -5,22 +5,25 @@ authService, tokenService, toastr, $analytics) { $analytics.eventTrack('settingsSessionsController', { category: 'Modal' }); $scope.submit = function (model) { - var request = { - masterPasswordHash: cryptoService.hashPassword(model.masterPassword) - }; + var hash, profile; - $scope.submitPromise = - authService.getUserProfile().then(function (profile) { - return apiService.accounts.putSecurityStamp(request, function () { - $uibModalInstance.dismiss('cancel'); - authService.logOut(); - tokenService.clearTwoFactorToken(profile.email); - $analytics.eventTrack('Deauthorized Sessions'); - $state.go('frontend.login.info').then(function () { - toastr.success('Please log back in.', 'All Sessions Deauthorized'); - }); - }).$promise; - }); + $scope.submitPromise = cryptoService.hashPassword(model.masterPassword).then(function (theHash) { + hash = theHash; + return authService.getUserProfile(); + }).then(function (theProfile) { + profile = theProfile; + return apiService.accounts.putSecurityStamp({ + masterPasswordHash: hash + }).$promise; + }).then(function () { + $uibModalInstance.dismiss('cancel'); + authService.logOut(); + tokenService.clearTwoFactorToken(profile.email); + $analytics.eventTrack('Deauthorized Sessions'); + return $state.go('frontend.login.info'); + }).then(function () { + toastr.success('Please log back in.', 'All Sessions Deauthorized'); + }); }; $scope.close = function () { diff --git a/src/app/settings/settingsTwoStepAuthenticatorController.js b/src/app/settings/settingsTwoStepAuthenticatorController.js index f7e22da3d59..88422f6954d 100644 --- a/src/app/settings/settingsTwoStepAuthenticatorController.js +++ b/src/app/settings/settingsTwoStepAuthenticatorController.js @@ -10,12 +10,13 @@ _key = null; $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - var response = null; - $scope.authPromise = apiService.twoFactor.getAuthenticator({}, { - masterPasswordHash: _masterPasswordHash - }).$promise.then(function (apiResponse) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + _masterPasswordHash = hash; + return apiService.twoFactor.getAuthenticator({}, { + masterPasswordHash: _masterPasswordHash + }).$promise; + }).then(function (apiResponse) { response = apiResponse; return authService.getUserProfile(); }).then(function (profile) { diff --git a/src/app/settings/settingsTwoStepDuoController.js b/src/app/settings/settingsTwoStepDuoController.js index e073d6b0467..324ec96c1df 100644 --- a/src/app/settings/settingsTwoStepDuoController.js +++ b/src/app/settings/settingsTwoStepDuoController.js @@ -14,10 +14,12 @@ }; $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - $scope.authPromise = apiService.twoFactor.getDuo({}, { - masterPasswordHash: _masterPasswordHash - }).$promise.then(function (apiResponse) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + _masterPasswordHash = hash; + return apiService.twoFactor.getDuo({}, { + masterPasswordHash: _masterPasswordHash + }).$promise; + }).then(function (apiResponse) { processResult(apiResponse); $scope.authed = true; }); diff --git a/src/app/settings/settingsTwoStepEmailController.js b/src/app/settings/settingsTwoStepEmailController.js index 5eb0dfb8075..1563ae1db1a 100644 --- a/src/app/settings/settingsTwoStepEmailController.js +++ b/src/app/settings/settingsTwoStepEmailController.js @@ -13,12 +13,13 @@ }; $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - var response = null; - $scope.authPromise = apiService.twoFactor.getEmail({}, { - masterPasswordHash: _masterPasswordHash - }).$promise.then(function (apiResponse) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + _masterPasswordHash = hash; + return apiService.twoFactor.getEmail({}, { + masterPasswordHash: _masterPasswordHash + }).$promise; + }).then(function (apiResponse) { response = apiResponse; return authService.getUserProfile(); }).then(function (profile) { diff --git a/src/app/settings/settingsTwoStepRecoverController.js b/src/app/settings/settingsTwoStepRecoverController.js index 29a7995d570..7f8b30a7e7a 100644 --- a/src/app/settings/settingsTwoStepRecoverController.js +++ b/src/app/settings/settingsTwoStepRecoverController.js @@ -7,11 +7,11 @@ $scope.code = null; $scope.auth = function (model) { - var masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - - $scope.authPromise = apiService.twoFactor.getRecover({}, { - masterPasswordHash: masterPasswordHash - }).$promise.then(function (apiResponse) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + return apiService.twoFactor.getRecover({}, { + masterPasswordHash: hash + }).$promise; + }).then(function (apiResponse) { $scope.code = formatString(apiResponse.Code); $scope.authed = true; }); diff --git a/src/app/settings/settingsTwoStepU2fController.js b/src/app/settings/settingsTwoStepU2fController.js index 1ed689834c6..bab7c1cdd91 100644 --- a/src/app/settings/settingsTwoStepU2fController.js +++ b/src/app/settings/settingsTwoStepU2fController.js @@ -12,11 +12,12 @@ $scope.deviceError = false; $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - - $scope.authPromise = apiService.twoFactor.getU2f({}, { - masterPasswordHash: _masterPasswordHash - }).$promise.then(function (response) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + _masterPasswordHash = hash; + return apiService.twoFactor.getU2f({}, { + masterPasswordHash: _masterPasswordHash + }).$promise; + }).then(function (response) { $scope.enabled = response.Enabled; $scope.challenge = response.Challenge; $scope.authed = true; diff --git a/src/app/settings/settingsTwoStepYubiController.js b/src/app/settings/settingsTwoStepYubiController.js index 05e2c274da8..ca1f2404014 100644 --- a/src/app/settings/settingsTwoStepYubiController.js +++ b/src/app/settings/settingsTwoStepYubiController.js @@ -8,12 +8,13 @@ _masterPasswordHash; $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - var response = null; - $scope.authPromise = apiService.twoFactor.getYubi({}, { - masterPasswordHash: _masterPasswordHash - }).$promise.then(function (apiResponse) { + $scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) { + _masterPasswordHash = hash; + return apiService.twoFactor.getYubi({}, { + masterPasswordHash: _masterPasswordHash + }).$promise; + }).then(function (apiResponse) { response = apiResponse; return authService.getUserProfile(); }).then(function (profile) { diff --git a/src/app/settings/settingsUpdateKeyController.js b/src/app/settings/settingsUpdateKeyController.js index 9492d20366c..98097f4a91c 100644 --- a/src/app/settings/settingsUpdateKeyController.js +++ b/src/app/settings/settingsUpdateKeyController.js @@ -14,8 +14,9 @@ } $scope.processing = true; - var mpHash = cryptoService.hashPassword($scope.masterPassword); - $scope.savePromise = cipherService.updateKey(mpHash, function () { + $scope.savePromise = cryptoService.hashPassword($scope.masterPassword).then(function (hash) { + return cipherService.updateKey(hash); + }).then(function () { $uibModalInstance.dismiss('cancel'); authService.logOut(); $analytics.eventTrack('Key Updated'); @@ -23,14 +24,12 @@ }).then(function () { toastr.success('Please log back in. If you are using other bitwarden applications, ' + 'log out and back in to those as well.', 'Key Updated', { timeOut: 10000 }); - }, processError); + }, function () { + $uibModalInstance.dismiss('cancel'); + toastr.error('Something went wrong.', 'Oh No!'); + }); }; - function processError() { - $uibModalInstance.dismiss('cancel'); - toastr.error('Something went wrong.', 'Oh No!'); - } - $scope.close = function () { $uibModalInstance.dismiss('cancel'); }; diff --git a/src/app/tools/views/toolsExport.html b/src/app/tools/views/toolsExport.html index afcb8b39861..2a2ecf05521 100644 --- a/src/app/tools/views/toolsExport.html +++ b/src/app/tools/views/toolsExport.html @@ -18,8 +18,8 @@
- +