diff --git a/src/app/accounts/accountsRecoverController.js b/src/app/accounts/accountsRecoverController.js index 67e1577a8e..d16fba83d1 100644 --- a/src/app/accounts/accountsRecoverController.js +++ b/src/app/accounts/accountsRecoverController.js @@ -14,7 +14,7 @@ angular recoveryCode: model.code.replace(/\s/g, '').toLowerCase() }; - $scope.submitPromise = apiService.accounts.postTwoFactorRecover(request, function () { + $scope.submitPromise = apiService.twoFactor.recover(request, function () { $analytics.eventTrack('Recovered 2FA'); $scope.success = true; }).$promise; diff --git a/src/app/services/apiService.js b/src/app/services/apiService.js index 4409c42acd..82070316d8 100644 --- a/src/app/services/apiService.js +++ b/src/app/services/apiService.js @@ -103,9 +103,6 @@ putProfile: { url: _apiUri + '/accounts/profile', method: 'POST', params: {} }, getDomains: { url: _apiUri + '/accounts/domains', method: 'GET', params: {} }, putDomains: { url: _apiUri + '/accounts/domains', method: 'POST', params: {} }, - getTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'GET', params: {} }, - putTwoFactor: { url: _apiUri + '/accounts/two-factor', method: 'POST', params: {} }, - postTwoFactorRecover: { url: _apiUri + '/accounts/two-factor-recover', method: 'POST', params: {} }, postPasswordHint: { url: _apiUri + '/accounts/password-hint', method: 'POST', params: {} }, putSecurityStamp: { url: _apiUri + '/accounts/security-stamp', method: 'POST', params: {} }, putKeys: { url: _apiUri + '/accounts/keys', method: 'POST', params: {} }, @@ -115,8 +112,13 @@ }); _service.twoFactor = $resource(_apiUri + '/two-factor', {}, { - get: { method: 'GET', params: { provider: '@provider' } }, - list: { method: 'GET', params: {} } + list: { method: 'GET', params: {} }, + getEmail: { url: _apiUri + '/two-factor/get-email', method: 'POST', params: {} }, + getAuthenticator: { url: _apiUri + '/two-factor/get-authenticator', method: 'POST', params: {} }, + putEmail: { url: _apiUri + '/two-factor/email', method: 'POST', params: {} }, + putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} }, + disable: { url: _apiUri + '/two-factor/disable', method: 'POST', params: {} }, + recover: { url: _apiUri + '/two-factor/recover', method: 'POST', params: {} }, }); _service.settings = $resource(_apiUri + '/settings', {}, { diff --git a/src/app/settings/settingsController.js b/src/app/settings/settingsController.js index 474fb57c94..330ea42600 100644 --- a/src/app/settings/settingsController.js +++ b/src/app/settings/settingsController.js @@ -105,22 +105,6 @@ }); }; - $scope.twoFactor = function () { - var twoFactorModal = $uibModal.open({ - animation: true, - templateUrl: 'app/settings/views/settingsTwoFactor.html', - controller: 'settingsTwoFactorController' - }); - - twoFactorModal.result.then(function (enabled) { - if (enabled === null) { - return; - } - - $scope.model.twoFactorEnabled = enabled; - }); - }; - $scope.sessions = function () { $uibModal.open({ animation: true, diff --git a/src/app/settings/settingsTwoFactorController.js b/src/app/settings/settingsTwoFactorController.js deleted file mode 100644 index a430ca41a6..0000000000 --- a/src/app/settings/settingsTwoFactorController.js +++ /dev/null @@ -1,93 +0,0 @@ -angular - .module('bit.settings') - - .controller('settingsTwoFactorController', function ($scope, apiService, $uibModalInstance, cryptoService, authService, - $q, toastr, $analytics) { - $analytics.eventTrack('settingsTwoFactorController', { category: 'Modal' }); - var _issuer = 'bitwarden', - _profile = null, - _masterPasswordHash; - - authService.getUserProfile().then(function (profile) { - _profile = profile; - $scope.account = _profile.email; - $scope.enabled = function () { - return _profile.extended && _profile.extended.twoFactorEnabled; - }; - }); - - $scope.auth = function (model) { - _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); - - $scope.authPromise = apiService.accounts.getTwoFactor({ - masterPasswordHash: _masterPasswordHash, - provider: 0 /* Only authenticator provider for now. */ - }, function (response) { - processResponse(response); - }).$promise; - }; - - function formatString(s) { - if (!s) { - return null; - } - - return s.replace(/(.{4})/g, '$1 ').trim().toUpperCase(); - } - - function processResponse(response) { - var key = response.AuthenticatorKey; - $scope.twoFactorModel = { - enabled: response.TwoFactorEnabled, - key: formatString(key), - recovery: formatString(response.TwoFactorRecoveryCode), - qr: 'https://chart.googleapis.com/chart?chs=120x120&chld=L|0&cht=qr&chl=otpauth://totp/' + - _issuer + ':' + encodeURIComponent(_profile.email) + - '%3Fsecret=' + encodeURIComponent(key) + - '%26issuer=' + _issuer - }; - } - - $scope.update = function (model) { - var currentlyEnabled = $scope.twoFactorModel.enabled; - if (currentlyEnabled && !confirm('Are you sure you want to disable two-step login?')) { - return; - } - - var request = { - enabled: !currentlyEnabled, - token: model.token.replace(' ', ''), - masterPasswordHash: _masterPasswordHash - }; - - $scope.updatePromise = apiService.accounts.putTwoFactor({}, request, function (response) { - if (response.TwoFactorEnabled) { - $analytics.eventTrack('Enabled Two-step Login'); - toastr.success('Two-step login has been enabled.'); - if (_profile.extended) _profile.extended.twoFactorEnabled = true; - processResponse(response); - $('#token').blur(); - model.token = null; - } - else { - $analytics.eventTrack('Disabled Two-step Login'); - toastr.success('Two-step login has been disabled.'); - if (_profile.extended) _profile.extended.twoFactorEnabled = false; - $scope.close(); - } - }).$promise; - }; - - $scope.print = function (printContent) { - $analytics.eventTrack('Print Recovery Code'); - var w = window.open(); - w.document.write('

bitwarden two-step login recovery code:

' + - '
' + printContent + '
'); - w.print(); - w.close(); - }; - - $scope.close = function () { - $uibModalInstance.close(!_profile.extended ? null : _profile.extended.twoFactorEnabled); - }; - }); diff --git a/src/app/settings/settingsTwoStepAuthenticatorController.js b/src/app/settings/settingsTwoStepAuthenticatorController.js new file mode 100644 index 0000000000..5eca9beacc --- /dev/null +++ b/src/app/settings/settingsTwoStepAuthenticatorController.js @@ -0,0 +1,88 @@ +angular + .module('bit.settings') + + .controller('settingsTwoStepAuthenticatorController', function ($scope, apiService, $uibModalInstance, cryptoService, + authService, $q, toastr, $analytics, constants) { + $analytics.eventTrack('settingsTwoStepAuthenticatorController', { category: 'Modal' }); + var _issuer = 'bitwarden', + _profile = null, + _masterPasswordHash; + + $scope.auth = function (model) { + _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); + + var response = null; + $scope.authPromise = apiService.twoFactor.getAuthenticator({}, { + masterPasswordHash: _masterPasswordHash + }).$promise.then(function (apiResponse) { + response = apiResponse; + return authService.getUserProfile(); + }).then(function (profile) { + _profile = profile; + $scope.account = _profile.email; + processResponse(response); + }); + }; + + function formatString(s) { + if (!s) { + return null; + } + + return s.replace(/(.{4})/g, '$1 ').trim().toUpperCase(); + } + + function processResponse(response) { + $scope.enabled = response.Enabled; + + $scope.model = { + key: formatString(response.Key), + qr: 'https://chart.googleapis.com/chart?chs=120x120&chld=L|0&cht=qr&chl=otpauth://totp/' + + _issuer + ':' + encodeURIComponent(_profile.email) + + '%3Fsecret=' + encodeURIComponent(response.Key) + + '%26issuer=' + _issuer + }; + $scope.updateModel = { + token: null + }; + } + + $scope.submit = function (model) { + if (!model || !model.token) { + disable(); + return; + } + + update(model); + }; + + function disable() { + if (!confirm('Are you sure you want to disable the authenticator app provider?')) { + return; + } + + $scope.submitPromise = apiService.twoFactor.disable({}, { + masterPasswordHash: _masterPasswordHash, + type: constants.twoFactorProvider.authenticator + }, function (response) { + $analytics.eventTrack('Disabled Two-step Authenticator'); + toastr.success('Authenticator app has been disabled.'); + $scope.close(); + }).$promise; + } + + function update(model) { + $scope.submitPromise = apiService.twoFactor.putAuthenticator({}, { + token: model.token.replace(' ', ''), + masterPasswordHash: _masterPasswordHash + }, function (response) { + $analytics.eventTrack('Enabled Two-step Authenticator'); + processResponse(response); + model.token = null; + }).$promise; + } + + $scope.close = function () { + $uibModalInstance.close(); + }; + }); diff --git a/src/app/settings/settingsTwoStepController.js b/src/app/settings/settingsTwoStepController.js index 6ac15275fa..2fb6ea8ae0 100644 --- a/src/app/settings/settingsTwoStepController.js +++ b/src/app/settings/settingsTwoStepController.js @@ -2,7 +2,7 @@ .module('bit.settings') .controller('settingsTwoStepController', function ($scope, apiService, authService, toastr, $analytics, constants, - $filter) { + $filter, $uibModal) { $scope.providers = [ { type: constants.twoFactorProvider.authenticator, @@ -53,4 +53,21 @@ authService.getUserProfile().then(function (profile) { _profile = profile; }); + + $scope.edit = function (provider) { + if (provider.type === constants.twoFactorProvider.authenticator) { + var authenticatorModal = $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsTwoStepAuthenticator.html', + controller: 'settingsTwoStepAuthenticatorController', + resolve: { + enabled: function () { return provider.enabled; } + } + }); + + authenticatorModal.result.then(function () { + + }); + } + }; }); diff --git a/src/app/settings/views/settings.html b/src/app/settings/views/settings.html index 3b780c6d24..9f53ab2dd8 100644 --- a/src/app/settings/views/settings.html +++ b/src/app/settings/views/settings.html @@ -85,27 +85,6 @@
-
-
-

Two-step Log In

-
-
-

- Current Status: - ENABLED - DISABLED -

-

- Two-step login helps keep your account more secure by requiring a code provided by an app on your mobile device - while logging in (in addition to your master password). -

-
- -

Organizations

diff --git a/src/app/settings/views/settingsTwoFactor.html b/src/app/settings/views/settingsTwoStepAuthenticator.html similarity index 50% rename from src/app/settings/views/settingsTwoFactor.html rename to src/app/settings/views/settingsTwoStepAuthenticator.html index 9226b63a0c..33621e199e 100644 --- a/src/app/settings/views/settingsTwoFactor.html +++ b/src/app/settings/views/settingsTwoStepAuthenticator.html @@ -1,15 +1,13 @@ 
+ ng-if="!model">