mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
org 2fa management for duo
This commit is contained in:
parent
08b2184e12
commit
24bf1363ab
@ -26,7 +26,8 @@ angular.module('bit')
|
||||
duo: 2,
|
||||
authenticator: 0,
|
||||
email: 1,
|
||||
remember: 5
|
||||
remember: 5,
|
||||
organizationDuo: 6
|
||||
},
|
||||
cipherType: {
|
||||
login: 1,
|
||||
@ -153,6 +154,19 @@ angular.module('bit')
|
||||
requiresUsb: false
|
||||
}
|
||||
],
|
||||
orgTwoFactorProviderInfo: [
|
||||
{
|
||||
type: 6,
|
||||
name: 'Duo',
|
||||
description: 'Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.',
|
||||
enabled: false,
|
||||
active: true,
|
||||
image: 'duo.png',
|
||||
displayOrder: 1,
|
||||
priority: 0,
|
||||
requiresUsb: false
|
||||
}
|
||||
],
|
||||
plans: {
|
||||
free: {
|
||||
basePrice: 0,
|
||||
|
@ -2,11 +2,14 @@
|
||||
.module('bit.organization')
|
||||
|
||||
.controller('organizationSettingsController', function ($scope, $state, apiService, toastr, authService, $uibModal,
|
||||
$analytics, appSettings) {
|
||||
$analytics, appSettings, constants, $filter) {
|
||||
$scope.selfHosted = appSettings.selfHosted;
|
||||
$scope.model = {};
|
||||
$scope.twoStepProviders = constants.orgTwoFactorProviderInfo;
|
||||
$scope.use2fa = false;
|
||||
|
||||
$scope.$on('$viewContentLoaded', function () {
|
||||
apiService.organizations.get({ id: $state.params.orgId }, function (org) {
|
||||
apiService.organizations.get({ id: $state.params.orgId }).$promise.then(function (org) {
|
||||
$scope.model = {
|
||||
name: org.Name,
|
||||
billingEmail: org.BillingEmail,
|
||||
@ -17,6 +20,29 @@
|
||||
businessCountry: org.BusinessCountry,
|
||||
businessTaxNumber: org.BusinessTaxNumber
|
||||
};
|
||||
|
||||
$scope.use2fa = org.Use2fa;
|
||||
if (org.Use2fa) {
|
||||
return apiService.twoFactor.listOrganization({ orgId: $state.params.orgId }).$promise;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}).then(function (response) {
|
||||
if (!response || !response.Data) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < response.Data.length; i++) {
|
||||
if (!response.Data[i].Enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var provider = $filter('filter')($scope.twoStepProviders, { type: response.Data[i].Type });
|
||||
if (provider.length) {
|
||||
provider[0].enabled = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -56,4 +82,30 @@
|
||||
controller: 'organizationDeleteController'
|
||||
});
|
||||
};
|
||||
|
||||
$scope.edit = function (provider) {
|
||||
if (provider.type === constants.twoFactorProvider.organizationDuo) {
|
||||
typeName = 'Duo';
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
var modal = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: 'app/settings/views/settingsTwoStep' + typeName + '.html',
|
||||
controller: 'settingsTwoStep' + typeName + 'Controller',
|
||||
resolve: {
|
||||
enabled: function () { return provider.enabled; },
|
||||
orgId: function () { return $state.params.orgId; }
|
||||
}
|
||||
});
|
||||
|
||||
modal.result.then(function (enabled) {
|
||||
if (enabled || enabled === false) {
|
||||
// do not adjust when undefined or null
|
||||
provider.enabled = enabled;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
@ -63,6 +63,36 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="box box-default" ng-if="use2fa">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Two-step Login Providers</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-vmiddle">
|
||||
<tbody>
|
||||
<tr ng-repeat="provider in twoStepProviders | orderBy: 'displayOrder'">
|
||||
<td style="width: 120px; height: 75px;" align="center">
|
||||
<a href="#" stop-click ng-click="edit(provider)">
|
||||
<img alt="{{::provider.name}}" ng-src="{{'images/two-factor/' + provider.image}}" />
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" stop-click ng-click="edit(provider)">{{::provider.name}}</a>
|
||||
<div class="text-muted text-sm">{{::provider.description}}</div>
|
||||
</td>
|
||||
<td style="width: 100px;" class="text-right">
|
||||
<span class="label label-full"
|
||||
ng-class="{ 'label-success': provider.enabled, 'label-default': !provider.enabled }">
|
||||
{{provider.enabled ? 'Enabled' : 'Disabled'}}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Import/Export</h3>
|
||||
|
@ -160,9 +160,11 @@
|
||||
|
||||
_service.twoFactor = $resource(_apiUri + '/two-factor', {}, {
|
||||
list: { method: 'GET', params: {} },
|
||||
listOrganization: { url: _apiUri + '/organizations/:orgId/two-factor', method: 'GET', params: { orgId: '@orgId' } },
|
||||
getEmail: { url: _apiUri + '/two-factor/get-email', method: 'POST', params: {} },
|
||||
getU2f: { url: _apiUri + '/two-factor/get-u2f', method: 'POST', params: {} },
|
||||
getDuo: { url: _apiUri + '/two-factor/get-duo', method: 'POST', params: {} },
|
||||
getOrganizationDuo: { url: _apiUri + '/organizations/:orgId/two-factor/get-duo', method: 'POST', params: { orgId: '@orgId' } },
|
||||
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: {} },
|
||||
@ -171,8 +173,10 @@
|
||||
putU2f: { url: _apiUri + '/two-factor/u2f', method: 'POST', params: {} },
|
||||
putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} },
|
||||
putDuo: { url: _apiUri + '/two-factor/duo', method: 'POST', params: {} },
|
||||
putOrganizationDuo: { url: _apiUri + '/organizations/:orgId/two-factor/duo', method: 'POST', params: { orgId: '@orgId' } },
|
||||
putYubi: { url: _apiUri + '/two-factor/yubikey', method: 'POST', params: {} },
|
||||
disable: { url: _apiUri + '/two-factor/disable', method: 'POST', params: {} },
|
||||
disableOrganization: { url: _apiUri + '/organizations/:orgId/two-factor/disable', method: 'POST', params: { orgId: '@orgId' } },
|
||||
recover: { url: _apiUri + '/two-factor/recover', method: 'POST', params: {} },
|
||||
getRecover: { url: _apiUri + '/two-factor/get-recover', method: 'POST', params: {} }
|
||||
});
|
||||
|
@ -152,6 +152,7 @@ angular
|
||||
useGroups: profile.Organizations[i].UseGroups,
|
||||
useDirectory: profile.Organizations[i].UseDirectory,
|
||||
useEvents: profile.Organizations[i].UseEvents,
|
||||
use2fa: profile.Organizations[i].Use2fa,
|
||||
useTotp: profile.Organizations[i].UseTotp
|
||||
};
|
||||
}
|
||||
@ -187,6 +188,7 @@ angular
|
||||
useGroups: org.UseGroups,
|
||||
useDirectory: org.UseDirectory,
|
||||
useEvents: org.UseEvents,
|
||||
use2fa: org.Use2fa,
|
||||
useTotp: org.UseTotp
|
||||
};
|
||||
profile.organizations[o.id] = o;
|
||||
|
@ -60,7 +60,8 @@
|
||||
templateUrl: 'app/settings/views/settingsTwoStep' + typeName + '.html',
|
||||
controller: 'settingsTwoStep' + typeName + 'Controller',
|
||||
resolve: {
|
||||
enabled: function () { return provider.enabled; }
|
||||
enabled: function () { return provider.enabled; },
|
||||
orgId: function () { return null; }
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
.module('bit.settings')
|
||||
|
||||
.controller('settingsTwoStepDuoController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||
toastr, $analytics, constants, $timeout) {
|
||||
toastr, $analytics, constants, $timeout, orgId) {
|
||||
$analytics.eventTrack('settingsTwoStepDuoController', { category: 'Modal' });
|
||||
var _masterPasswordHash;
|
||||
|
||||
@ -20,9 +20,16 @@
|
||||
$scope.auth = function (model) {
|
||||
$scope.authPromise = cryptoService.hashPassword(model.masterPassword).then(function (hash) {
|
||||
_masterPasswordHash = hash;
|
||||
return apiService.twoFactor.getDuo({}, {
|
||||
var requestModel = {
|
||||
masterPasswordHash: _masterPasswordHash
|
||||
}).$promise;
|
||||
};
|
||||
|
||||
if (orgId) {
|
||||
return apiService.twoFactor.getOrganizationDuo({ orgId: orgId }, requestModel).$promise;
|
||||
}
|
||||
else {
|
||||
return apiService.twoFactor.getDuo({}, requestModel).$promise;
|
||||
}
|
||||
}).then(function (apiResponse) {
|
||||
processResult(apiResponse);
|
||||
$scope.authed = true;
|
||||
@ -43,27 +50,52 @@
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.submitPromise = apiService.twoFactor.disable({}, {
|
||||
masterPasswordHash: _masterPasswordHash,
|
||||
type: constants.twoFactorProvider.duo
|
||||
}, function (response) {
|
||||
$analytics.eventTrack('Disabled Two-step Duo');
|
||||
toastr.success('Duo has been disabled.');
|
||||
$scope.enabled = response.Enabled;
|
||||
$scope.close();
|
||||
}).$promise;
|
||||
if (orgId) {
|
||||
$scope.submitPromise = apiService.twoFactor.disableOrganization({ orgId: orgId }, {
|
||||
masterPasswordHash: _masterPasswordHash,
|
||||
type: constants.twoFactorProvider.organizationDuo
|
||||
}, function (response) {
|
||||
$analytics.eventTrack('Disabled Two-step Organization Duo');
|
||||
toastr.success('Duo has been disabled.');
|
||||
$scope.enabled = response.Enabled;
|
||||
$scope.close();
|
||||
}).$promise;
|
||||
}
|
||||
else {
|
||||
$scope.submitPromise = apiService.twoFactor.disable({}, {
|
||||
masterPasswordHash: _masterPasswordHash,
|
||||
type: constants.twoFactorProvider.duo
|
||||
}, function (response) {
|
||||
$analytics.eventTrack('Disabled Two-step Duo');
|
||||
toastr.success('Duo has been disabled.');
|
||||
$scope.enabled = response.Enabled;
|
||||
$scope.close();
|
||||
}).$promise;
|
||||
}
|
||||
}
|
||||
|
||||
function update(model) {
|
||||
$scope.submitPromise = apiService.twoFactor.putDuo({}, {
|
||||
var requestModel = {
|
||||
integrationKey: model.ikey,
|
||||
secretKey: model.skey,
|
||||
host: model.host,
|
||||
masterPasswordHash: _masterPasswordHash
|
||||
}, function (response) {
|
||||
$analytics.eventTrack('Enabled Two-step Duo');
|
||||
processResult(response);
|
||||
}).$promise;
|
||||
};
|
||||
|
||||
if (orgId) {
|
||||
$scope.submitPromise = apiService.twoFactor.putOrganizationDuo({ orgId: orgId }, requestModel,
|
||||
function (response) {
|
||||
$analytics.eventTrack('Enabled Two-step Organization Duo');
|
||||
processResult(response);
|
||||
}).$promise;
|
||||
}
|
||||
else {
|
||||
$scope.submitPromise = apiService.twoFactor.putDuo({}, requestModel,
|
||||
function (response) {
|
||||
$analytics.eventTrack('Enabled Two-step Duo');
|
||||
processResult(response);
|
||||
}).$promise;
|
||||
}
|
||||
}
|
||||
|
||||
function processResult(response) {
|
||||
@ -80,7 +112,7 @@
|
||||
closing = true;
|
||||
$uibModalInstance.close($scope.enabled);
|
||||
};
|
||||
|
||||
|
||||
$scope.$on('modal.closing', function (e, reason, closed) {
|
||||
if (closing) {
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user