mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-28 12:45:45 +01:00
move pbkdf2 to web crypto with shim fallback
This commit is contained in:
parent
b62950fa2b
commit
bc8892a237
@ -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 + '.');
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
@ -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: {
|
||||
|
@ -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');
|
||||
|
@ -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;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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 () {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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');
|
||||
};
|
||||
|
@ -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 () {
|
||||
|
@ -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 () {
|
||||
|
@ -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 () {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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');
|
||||
};
|
||||
|
@ -18,8 +18,8 @@
|
||||
</div>
|
||||
<div class="form-group" show-errors>
|
||||
<label for="masterPassword">Master Password</label>
|
||||
<input type="password" id="masterPassword" name="MasterPasswordHash" ng-model="model.masterPassword" class="form-control"
|
||||
master-password required api-field ng-model-options="{ 'updateOn': 'blur'}" />
|
||||
<input type="password" id="masterPassword" name="MasterPasswordHash" ng-model="model.masterPassword"
|
||||
class="form-control" master-password required api-field ng-model-options="{ 'updateOn': 'blur'}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
@ -25,6 +25,9 @@
|
||||
isWebkit = !_crypto.subtle && !!_crypto.webkitSubtle;
|
||||
if (!isIE && !isWebkit) return;
|
||||
|
||||
// Added
|
||||
global.cryptoShimmed = true;
|
||||
|
||||
function s2a(s) {
|
||||
return btoa(s).replace(/\=+$/, '').replace(/\+/g, '-').replace(/\//g, '_');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user