diff --git a/lam/lib/webauthn.inc b/lam/lib/webauthn.inc
index a41d0f34..bcf1e097 100644
--- a/lam/lib/webauthn.inc
+++ b/lam/lib/webauthn.inc
@@ -100,14 +100,15 @@ class WebauthnManager {
*
* @param string $dn DN
* @param bool $isSelfService is executed in self service
+ * @param array $extraExcludedKeys credentialIds that should be added to excluded keys
* @return PublicKeyCredentialCreationOptions registration object
*/
- public function getRegistrationObject($dn, $isSelfService) {
+ public function getRegistrationObject($dn, $isSelfService, $extraExcludedKeys = array()) {
$rpEntity = $this->createRpEntry($isSelfService);
$userEntity = $this->getUserEntity($dn);
$challenge = $this->createChallenge();
$credentialParameters = $this->getCredentialParameters();
- $excludedKeys = $this->getExcludedKeys($userEntity);
+ $excludedKeys = $this->getExcludedKeys($userEntity, $extraExcludedKeys);
$timeout = $this->getTimeout();
$registrationObject = new PublicKeyCredentialCreationOptions(
$rpEntity,
@@ -161,6 +162,18 @@ class WebauthnManager {
return false;
}
+ /**
+ * Returns a public key credential loader.
+ *
+ * @return PublicKeyCredentialLoader public key credential loader
+ */
+ public function createPublicKeyCredentialLoader() {
+ $decoder = $this->getCborDecoder();
+ $attestationSupportManager = $this->getAttestationSupportManager($decoder);
+ $attestationObjectLoader = $this->getAttestationObjectLoader($attestationSupportManager, $decoder);
+ return $this->getPublicKeyCredentialLoader($attestationObjectLoader, $decoder);
+ }
+
/**
* Returns the user entity for the registration.
*
@@ -214,15 +227,19 @@ class WebauthnManager {
* Returns a list of all credential ids that are already registered.
*
* @param PublicKeyCredentialUserEntity $user user data
+ * @param array $extraExcludedKeys credentialIds that should be added to excluded keys
* @return PublicKeyCredentialDescriptor[] credential ids
*/
- private function getExcludedKeys($user) {
+ private function getExcludedKeys($user, $extraExcludedKeys = array()) {
$keys = array();
$repository = $this->getDatabase();
$credentialSources = $repository->findAllForUserEntity($user);
foreach ($credentialSources as $credentialSource) {
$keys[] = new PublicKeyCredentialDescriptor(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $credentialSource->getPublicKeyCredentialId());
}
+ foreach ($extraExcludedKeys as $extraExcludedKey) {
+ $keys[] = new PublicKeyCredentialDescriptor(PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY, $extraExcludedKey);
+ }
return $keys;
}
diff --git a/lam/templates/lib/500_lam.js b/lam/templates/lib/500_lam.js
index 053b8aa0..3c7c782d 100644
--- a/lam/templates/lib/500_lam.js
+++ b/lam/templates/lib/500_lam.js
@@ -1620,15 +1620,18 @@ window.lam.webauthn.removeDevice = function(event) {
window.lam.webauthn.removeOwnDevice = function(event, isSelfService) {
event.preventDefault();
const element = jQuery(event.currentTarget);
- const successCallback = function () {
- const form = jQuery("#webauthnform");
- jQuery('').attr({
- type: 'hidden',
- name: 'removed',
- value: 'true'
- }).appendTo(form);
- form.submit();
- };
+ let successCallback = null;
+ if (!isSelfService) {
+ successCallback = function () {
+ const form = jQuery("#webauthnform");
+ jQuery('').attr({
+ type: 'hidden',
+ name: 'removed',
+ value: 'true'
+ }).appendTo(form);
+ form.submit();
+ };
+ }
let action = 'webauthnOwnDevices';
if (isSelfService) {
action = action + '&selfservice=true&module=webauthn&scope=user';
@@ -1706,21 +1709,44 @@ window.lam.webauthn.sendRemoveDeviceRequest = function(element, action, successC
* Registers a user's own webauthn device.
*
* @param event click event
+ * @param isSelfService runs in self service context
*/
-window.lam.webauthn.registerOwnDevice = function(event) {
+window.lam.webauthn.registerOwnDevice = function(event, isSelfService) {
event.preventDefault();
const element = jQuery(event.target);
const dn = element.data('dn');
const tokenValue = element.data('sec_token_value');
- const tokenName = element.data('sec_token_name');
const publicKey = element.data('publickey');
- const successCallback = function (publicKeyCredential) {
+ let successCallback = function (publicKeyCredential) {
const form = jQuery("#webauthnform");
const response = btoa(JSON.stringify(publicKeyCredential));
const registrationData = jQuery('#registrationData');
registrationData.val(response);
form.submit();
};
+ if (isSelfService) {
+ successCallback = function (publicKeyCredential) {
+ const data = {
+ action: 'register',
+ jsonInput: '',
+ sec_token: tokenValue,
+ dn: dn,
+ credential: btoa(JSON.stringify(publicKeyCredential))
+ };
+ jQuery.ajax({
+ url: '../misc/ajax.php?selfservice=true&module=webauthn&scope=user',
+ method: 'POST',
+ data: data
+ })
+ .done(function(jsonData) {
+ const resultDiv = jQuery('#webauthn_results');
+ resultDiv.html(jsonData.content);
+ })
+ .fail(function() {
+ console.log('Webauthn device registration failed');
+ });
+ };
+ }
const errorCallback = function (error) {
let errorDiv = jQuery('#generic-webauthn-error');
let buttonLabel = errorDiv.data('button');
diff --git a/lam/templates/tools/webauthn.php b/lam/templates/tools/webauthn.php
index 04147ada..1b9e23f5 100644
--- a/lam/templates/tools/webauthn.php
+++ b/lam/templates/tools/webauthn.php
@@ -88,7 +88,7 @@ $registrationJson = json_encode($registration);
$_SESSION['webauthn_registration'] = $registrationJson;
$registerButton->addDataAttribute('publickey', $registrationJson);
$registerButton->setIconClass('createButton');
-$registerButton->setOnClick('window.lam.webauthn.registerOwnDevice(event);');
+$registerButton->setOnClick('window.lam.webauthn.registerOwnDevice(event, false);');
$buttonGroup->addElement($registerButton);
$buttonGroup->addElement(new htmlSpacer('1rem', null));
$reloadButton = new htmlButton('reload', _('Reload'));