configure u2f device
This commit is contained in:
parent
e366b7c7a7
commit
0135476b68
|
@ -114,11 +114,13 @@
|
||||||
_service.twoFactor = $resource(_apiUri + '/two-factor', {}, {
|
_service.twoFactor = $resource(_apiUri + '/two-factor', {}, {
|
||||||
list: { method: 'GET', params: {} },
|
list: { method: 'GET', params: {} },
|
||||||
getEmail: { url: _apiUri + '/two-factor/get-email', method: 'POST', params: {} },
|
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: {} },
|
getDuo: { url: _apiUri + '/two-factor/get-duo', method: 'POST', params: {} },
|
||||||
getAuthenticator: { url: _apiUri + '/two-factor/get-authenticator', method: 'POST', params: {} },
|
getAuthenticator: { url: _apiUri + '/two-factor/get-authenticator', method: 'POST', params: {} },
|
||||||
getYubi: { url: _apiUri + '/two-factor/get-yubikey', method: 'POST', params: {} },
|
getYubi: { url: _apiUri + '/two-factor/get-yubikey', method: 'POST', params: {} },
|
||||||
sendEmail: { url: _apiUri + '/two-factor/send-email', method: 'POST', params: {} },
|
sendEmail: { url: _apiUri + '/two-factor/send-email', method: 'POST', params: {} },
|
||||||
putEmail: { url: _apiUri + '/two-factor/email', method: 'POST', params: {} },
|
putEmail: { url: _apiUri + '/two-factor/email', method: 'POST', params: {} },
|
||||||
|
putU2f: { url: _apiUri + '/two-factor/u2f', method: 'POST', params: {} },
|
||||||
putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} },
|
putAuthenticator: { url: _apiUri + '/two-factor/authenticator', method: 'POST', params: {} },
|
||||||
putDuo: { url: _apiUri + '/two-factor/duo', method: 'POST', params: {} },
|
putDuo: { url: _apiUri + '/two-factor/duo', method: 'POST', params: {} },
|
||||||
putYubi: { url: _apiUri + '/two-factor/yubikey', method: 'POST', params: {} },
|
putYubi: { url: _apiUri + '/two-factor/yubikey', method: 'POST', params: {} },
|
||||||
|
|
|
@ -111,5 +111,19 @@
|
||||||
provider.enabled = enabled;
|
provider.enabled = enabled;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (provider.type === constants.twoFactorProvider.u2f) {
|
||||||
|
var u2fModal = $uibModal.open({
|
||||||
|
animation: true,
|
||||||
|
templateUrl: 'app/settings/views/settingsTwoStepU2f.html',
|
||||||
|
controller: 'settingsTwoStepU2fController',
|
||||||
|
resolve: {
|
||||||
|
enabled: function () { return provider.enabled; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
u2fModal.result.then(function (enabled) {
|
||||||
|
provider.enabled = enabled;
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
angular
|
||||||
|
.module('bit.settings')
|
||||||
|
|
||||||
|
.controller('settingsTwoStepU2fController', function ($scope, apiService, $uibModalInstance, cryptoService,
|
||||||
|
authService, toastr, $analytics, constants, $timeout, $window) {
|
||||||
|
$analytics.eventTrack('settingsTwoStepU2fController', { category: 'Modal' });
|
||||||
|
var _masterPasswordHash;
|
||||||
|
|
||||||
|
$scope.deviceResponse = null;
|
||||||
|
$scope.deviceListening = false;
|
||||||
|
$scope.deviceError = false;
|
||||||
|
|
||||||
|
$scope.auth = function (model) {
|
||||||
|
_masterPasswordHash = cryptoService.hashPassword(model.masterPassword);
|
||||||
|
|
||||||
|
$scope.authPromise = apiService.twoFactor.getU2f({}, {
|
||||||
|
masterPasswordHash: _masterPasswordHash
|
||||||
|
}).$promise.then(function (response) {
|
||||||
|
$scope.enabled = response.Enabled;
|
||||||
|
$scope.challenge = response.Challenge;
|
||||||
|
$scope.authed = true;
|
||||||
|
return $scope.readDevice();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.readDevice = function () {
|
||||||
|
$scope.deviceResponse = null;
|
||||||
|
$scope.deviceError = false;
|
||||||
|
$scope.deviceListening = true;
|
||||||
|
|
||||||
|
$window.u2f.register($scope.challenge.AppId, [{
|
||||||
|
version: $scope.challenge.Version,
|
||||||
|
challenge: $scope.challenge.Challenge
|
||||||
|
}], [], function (data) {
|
||||||
|
$scope.deviceListening = false;
|
||||||
|
|
||||||
|
console.log('call back data:');
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
if (data.errorCode) {
|
||||||
|
$scope.deviceError = true;
|
||||||
|
$scope.$apply();
|
||||||
|
console.log('error: ' + data.errorCode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.deviceResponse = JSON.stringify(data);
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.submit = function () {
|
||||||
|
if ($scope.enabled) {
|
||||||
|
disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
};
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
if (!confirm('Are you sure you want to disable the U2F provider?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.submitPromise = apiService.twoFactor.disable({}, {
|
||||||
|
masterPasswordHash: _masterPasswordHash,
|
||||||
|
type: constants.twoFactorProvider.u2f
|
||||||
|
}, function (response) {
|
||||||
|
$analytics.eventTrack('Disabled Two-step U2F');
|
||||||
|
toastr.success('U2F has been disabled.');
|
||||||
|
$scope.enabled = response.Enabled;
|
||||||
|
$scope.close();
|
||||||
|
}).$promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
$scope.submitPromise = apiService.twoFactor.putU2f({}, {
|
||||||
|
deviceResponse: $scope.deviceResponse,
|
||||||
|
masterPasswordHash: _masterPasswordHash
|
||||||
|
}, function (response) {
|
||||||
|
$analytics.eventTrack('Enabled Two-step U2F');
|
||||||
|
$scope.enabled = response.Enabled;
|
||||||
|
$scope.challenge = null;
|
||||||
|
$scope.deviceResponse = null;
|
||||||
|
$scope.deviceError = false;
|
||||||
|
}).$promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.close = function () {
|
||||||
|
$uibModalInstance.close($scope.enabled);
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,76 @@
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title">
|
||||||
|
<i class="fa fa-key"></i> Two-step Login <small>fido u2f</small>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<form name="authTwoStepForm" ng-submit="authTwoStepForm.$valid && auth(authModel)" api-form="authPromise"
|
||||||
|
ng-if="!authed">
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Enter your master password to modify two-step login settings.</p>
|
||||||
|
<div class="callout callout-danger validation-errors" ng-show="authTwoStepForm.$errors">
|
||||||
|
<h4>Errors have occurred</h4>
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="e in authTwoStepForm.$errors">{{e}}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" show-errors>
|
||||||
|
<label for="masterPassword">Master Password</label>
|
||||||
|
<input type="password" id="masterPassword" name="MasterPasswordHash" ng-model="authModel.masterPassword"
|
||||||
|
class="form-control" required api-field />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="authTwoStepForm.$loading">
|
||||||
|
<i class="fa fa-refresh fa-spin loading-icon" ng-show="authTwoStepForm.$loading"></i>Continue
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form name="submitTwoStepForm" ng-submit="submitTwoStepForm.$valid && submit()" api-form="submitPromise"
|
||||||
|
ng-if="authed">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div ng-if="enabled">
|
||||||
|
<div class="callout callout-success">
|
||||||
|
<h4><i class="fa fa-check-circle"></i> Enabled</h4>
|
||||||
|
<p>Two-step log via FIDO U2F is enabled on your account.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-if="!enabled">
|
||||||
|
<div class="callout callout-danger validation-errors" ng-show="submitTwoStepForm.$errors">
|
||||||
|
<h4>Errors have occurred</h4>
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="e in submitTwoStepForm.$errors">{{e}}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p>Setting up two-step login with a FIDO U2F security key is easy, just follow these steps:</p>
|
||||||
|
<h4>1. Plug your security key into your USB port</h4>
|
||||||
|
<h4 style="margin-top: 30px;">2. Touch the button on the security key</h4>
|
||||||
|
<p>
|
||||||
|
<button type="button" ng-click="readDevice()" class="btn btn-default btn-flat">
|
||||||
|
<i class="fa fa-spin fa-refresh fa-fw" ng-show="deviceListening"></i>
|
||||||
|
<i class="fa fa-wifi fa-fw" ng-show="!deviceListening"></i>
|
||||||
|
Read Security Key
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
<div ng-show="deviceListening">
|
||||||
|
Waiting for you to touch the button on your security key...
|
||||||
|
</div>
|
||||||
|
<div class="text-green" ng-show="deviceResponse">
|
||||||
|
<i class="fa fa-check"></i>
|
||||||
|
Got it! Click the "Enable" button below to enable this security key for two-step login.
|
||||||
|
</div>
|
||||||
|
<div class="text-red" ng-show="deviceError">
|
||||||
|
There was a problem reading the security key. Try again.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="submit" class="btn btn-primary btn-flat"
|
||||||
|
ng-disabled="(!enabled && !deviceResponse) || submitTwoStepForm.$loading">
|
||||||
|
<i class="fa fa-refresh fa-spin loading-icon" ng-show="submitTwoStepForm.$loading"></i>
|
||||||
|
{{enabled ? 'Disable' : 'Enable'}}
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -83,6 +83,7 @@
|
||||||
<script src="lib/bootstrap/js/bootstrap.js"></script>
|
<script src="lib/bootstrap/js/bootstrap.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
<script src="lib/admin-lte/js/app.js"></script>
|
<script src="lib/admin-lte/js/app.js"></script>
|
||||||
|
<script src="js/u2f-api.js"></script>
|
||||||
|
|
||||||
<script src="lib/forge/forge.js"></script>
|
<script src="lib/forge/forge.js"></script>
|
||||||
<script src="lib/papaparse/papaparse.js"></script>
|
<script src="lib/papaparse/papaparse.js"></script>
|
||||||
|
@ -194,6 +195,7 @@
|
||||||
<script src="app/settings/settingsChangeEmailController.js"></script>
|
<script src="app/settings/settingsChangeEmailController.js"></script>
|
||||||
<script src="app/settings/settingsTwoStepAuthenticatorController.js"></script>
|
<script src="app/settings/settingsTwoStepAuthenticatorController.js"></script>
|
||||||
<script src="app/settings/settingsTwoStepDuoController.js"></script>
|
<script src="app/settings/settingsTwoStepDuoController.js"></script>
|
||||||
|
<script src="app/settings/settingsTwoStepU2fController.js"></script>
|
||||||
<script src="app/settings/settingsTwoStepEmailController.js"></script>
|
<script src="app/settings/settingsTwoStepEmailController.js"></script>
|
||||||
<script src="app/settings/settingsTwoStepYubiController.js"></script>
|
<script src="app/settings/settingsTwoStepYubiController.js"></script>
|
||||||
<script src="app/settings/settingsSessionsController.js"></script>
|
<script src="app/settings/settingsSessionsController.js"></script>
|
||||||
|
|
Loading…
Reference in New Issue