From cf5b0635e4e6422cd4310d1fae0ed181d006fc72 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 20 Jun 2017 14:00:55 -0400 Subject: [PATCH] Yubikey 2fa setup --- src/app/services/apiService.js | 2 + src/app/settings/settingsTwoStepController.js | 14 ++ .../settings/settingsTwoStepYubiController.js | 107 ++++++++++++++++ .../views/settingsTwoStepAuthenticator.html | 7 +- .../settings/views/settingsTwoStepYubi.html | 121 ++++++++++++++++++ src/index.html | 1 + src/less/vault.less | 4 + 7 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 src/app/settings/settingsTwoStepYubiController.js create mode 100644 src/app/settings/views/settingsTwoStepYubi.html diff --git a/src/app/services/apiService.js b/src/app/services/apiService.js index e9dc9ffb..511ec7f2 100644 --- a/src/app/services/apiService.js +++ b/src/app/services/apiService.js @@ -115,9 +115,11 @@ list: { method: 'GET', params: {} }, getEmail: { url: _apiUri + '/two-factor/get-email', method: 'POST', params: {} }, getAuthenticator: { url: _apiUri + '/two-factor/get-authenticator', method: 'POST', params: {} }, + getYubi: { url: _apiUri + '/two-factor/get-yubikey', method: 'POST', params: {} }, sendEmail: { url: _apiUri + '/two-factor/send-email', method: 'POST', params: {} }, putEmail: { url: _apiUri + '/two-factor/email', method: 'POST', params: {} }, putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} }, + putYubi: { url: _apiUri + '/two-factor/yubikey', method: 'POST', params: {} }, disable: { url: _apiUri + '/two-factor/disable', method: 'POST', params: {} }, recover: { url: _apiUri + '/two-factor/recover', method: 'POST', params: {} }, }); diff --git a/src/app/settings/settingsTwoStepController.js b/src/app/settings/settingsTwoStepController.js index 2cbe6a0c..26aed1cb 100644 --- a/src/app/settings/settingsTwoStepController.js +++ b/src/app/settings/settingsTwoStepController.js @@ -81,6 +81,20 @@ emailModal.result.then(function () { + }); + } + else if (provider.type === constants.twoFactorProvider.yubikey) { + var yubiModal = $uibModal.open({ + animation: true, + templateUrl: 'app/settings/views/settingsTwoStepYubi.html', + controller: 'settingsTwoStepYubiController', + resolve: { + enabled: function () { return provider.enabled; } + } + }); + + yubiModal.result.then(function () { + }); } }; diff --git a/src/app/settings/settingsTwoStepYubiController.js b/src/app/settings/settingsTwoStepYubiController.js new file mode 100644 index 00000000..77943fe7 --- /dev/null +++ b/src/app/settings/settingsTwoStepYubiController.js @@ -0,0 +1,107 @@ +angular + .module('bit.settings') + + .controller('settingsTwoStepYubiController', function ($scope, apiService, $uibModalInstance, cryptoService, + authService, toastr, $analytics, constants) { + $analytics.eventTrack('settingsTwoStepYubiController', { category: 'Modal' }); + var _profile = null, + _masterPasswordHash; + + $scope.auth = function (model) { + _masterPasswordHash = cryptoService.hashPassword(model.masterPassword); + + var response = null; + $scope.authPromise = apiService.twoFactor.getYubi({}, { + masterPasswordHash: _masterPasswordHash + }).$promise.then(function (apiResponse) { + response = apiResponse; + return authService.getUserProfile(); + }).then(function (profile) { + _profile = profile; + processResult(response); + $scope.authed = true; + }); + }; + + $scope.remove = function (model) { + model.key = null; + model.existingKey = null; + }; + + $scope.submit = function (model) { + $scope.submitPromise = apiService.twoFactor.putYubi({}, { + key1: model.key1.key, + key2: model.key2.key, + key3: model.key3.key, + key4: model.key4.key, + key5: model.key5.key, + masterPasswordHash: _masterPasswordHash + }, function (response) { + $analytics.eventTrack('Saved Two-step YubiKey'); + toastr.success('YubiKey saved.'); + processResult(response); + }).$promise; + }; + + $scope.disable = function () { + if (!confirm('Are you sure you want to disable the YubiKey provider?')) { + return; + } + + $scope.disableLoading = true; + $scope.submitPromise = apiService.twoFactor.disable({}, { + masterPasswordHash: _masterPasswordHash, + type: constants.twoFactorProvider.yubikey + }, function (response) { + $scope.disableLoading = false; + $analytics.eventTrack('Disabled Two-step YubiKey'); + toastr.success('YubiKey has been disabled.'); + $scope.close(); + }, function (response) { + toastr.error('Failed to disable.'); + $scope.disableLoading = false; + }).$promise; + } + + function processResult(response) { + $scope.enabled = response.Enabled; + $scope.updateModel = { + key1: { + key: response.Key1, + existingKey: padRight(response.Key1, '*', 44) + }, + key2: { + key: response.Key2, + existingKey: padRight(response.Key2, '*', 44) + }, + key3: { + key: response.Key3, + existingKey: padRight(response.Key3, '*', 44) + }, + key4: { + key: response.Key4, + existingKey: padRight(response.Key4, '*', 44) + }, + key5: { + key: response.Key5, + existingKey: padRight(response.Key5, '*', 44) + } + }; + } + + function padRight(str, character, size) { + if (!str || !character || str.length >= size) { + return str; + } + + var max = (size - str.length) / character.length; + for (var i = 0; i < max; i++) { + str += character; + } + return str; + } + + $scope.close = function () { + $uibModalInstance.close(); + }; + }); diff --git a/src/app/settings/views/settingsTwoStepAuthenticator.html b/src/app/settings/views/settingsTwoStepAuthenticator.html index f4d6d4ce..33aa54f9 100644 --- a/src/app/settings/views/settingsTwoStepAuthenticator.html +++ b/src/app/settings/views/settingsTwoStepAuthenticator.html @@ -34,8 +34,11 @@

Enabled

- Two-step log in is enabled on your account. Incase you need to add it to another device, below is the QR - code (or key) required by your authenticator app. + Two-step login via authenticator app is enabled on your account. +

+

+ Incase you need to add it to another device, below is the QR code (or key) required by your + authenticator app.

Need a two-step authenticator app? Download one of the following:

diff --git a/src/app/settings/views/settingsTwoStepYubi.html b/src/app/settings/views/settingsTwoStepYubi.html new file mode 100644 index 00000000..f63a4616 --- /dev/null +++ b/src/app/settings/views/settingsTwoStepYubi.html @@ -0,0 +1,121 @@ + +
+ + +
+
+ + +
diff --git a/src/index.html b/src/index.html index 4d61b933..e79e1f58 100644 --- a/src/index.html +++ b/src/index.html @@ -190,6 +190,7 @@ + diff --git a/src/less/vault.less b/src/less/vault.less index 90cf402b..46977260 100644 --- a/src/less/vault.less +++ b/src/less/vault.less @@ -519,6 +519,10 @@ h1, h2, h3, h4, h5, h6 { color: @text-muted; } +.monospaced { + font-family: @font-family-monospace; +} + .tooltip-wrapper { display: inline-block; }