webauthn
This commit is contained in:
parent
03ced7c697
commit
9e1e0634e6
Binary file not shown.
After Width: | Height: | Size: 810 B |
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
namespace LAM\TOOLS\WEBAUTHN;
|
||||
use LAM\LIB\TWO_FACTOR\TwoFactorProviderService;
|
||||
|
||||
/*
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2020 Roland Gruber
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Webauthn device management.
|
||||
*
|
||||
* @author Roland Gruber
|
||||
* @package tools
|
||||
*/
|
||||
|
||||
/**
|
||||
* Webauthn device management.
|
||||
*
|
||||
* @package tools
|
||||
*/
|
||||
class toolWebauthn implements \LAMTool {
|
||||
|
||||
/**
|
||||
* Returns the name of the tool.
|
||||
*
|
||||
* @return string name
|
||||
*/
|
||||
function getName() {
|
||||
return "Webauthn";
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a description text for the tool.
|
||||
*
|
||||
* @return string description
|
||||
*/
|
||||
function getDescription() {
|
||||
return _("Here you can manage your webauthn devices.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a link to the tool page (relative to templates/).
|
||||
*
|
||||
* @return string link
|
||||
*/
|
||||
function getLink() {
|
||||
return "tools/webauthn.php";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the tool requires write access to LDAP.
|
||||
*
|
||||
* @return boolean true if write access is needed
|
||||
*/
|
||||
function getRequiresWriteAccess() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the tool requires password change rights.
|
||||
*
|
||||
* @return boolean true if password change rights are needed
|
||||
*/
|
||||
function getRequiresPasswordChangeRights() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the link to the tool image (relative to graphics/)
|
||||
*
|
||||
* @return string image URL
|
||||
*/
|
||||
function getImageLink() {
|
||||
return 'webauthn.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the prefered position of this tool on the tools page.
|
||||
* The position may be between 0 and 1000. 0 is the top position.
|
||||
*
|
||||
* @return int prefered position
|
||||
*/
|
||||
function getPosition() {
|
||||
return 800;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of sub tools or an empty array.
|
||||
*
|
||||
* @return array list of subtools (LAMTool)
|
||||
*/
|
||||
function getSubTools() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the tool is visible in the menu.
|
||||
*
|
||||
* @return boolean visible
|
||||
*/
|
||||
function isVisible() {
|
||||
return ($_SESSION['config']->getTwoFactorAuthentication() === TwoFactorProviderService::TWO_FACTOR_WEBAUTHN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a tool may be hidden by configuration in the LAM server profile.
|
||||
*
|
||||
* @return boolean hideable
|
||||
*/
|
||||
function isHideable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -49,7 +49,7 @@ use \LAMException;
|
|||
/*
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2019 Roland Gruber
|
||||
Copyright (C) 2019 - 2020 Roland Gruber
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -546,7 +546,7 @@ class PublicKeyCredentialSourceRepositorySQLite implements PublicKeyCredentialSo
|
|||
$pdo = $this->getPDO();
|
||||
$statement = $pdo->prepare('select * from ' . self::TABLE_NAME . ' where userId like :searchTerm');
|
||||
$statement->execute(array(
|
||||
':searchTerm' => '%' . $searchTerm . '%'
|
||||
':searchTerm' => $searchTerm
|
||||
));
|
||||
$results = $statement->fetchAll();
|
||||
$devices = array();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2003 - 2019 Roland Gruber
|
||||
Copyright (C) 2003 - 2020 Roland Gruber
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1581,18 +1581,41 @@ window.lam.webauthn.addDeviceActionListeners = function() {
|
|||
/**
|
||||
* Removes a webauthn device.
|
||||
*
|
||||
* @param element button
|
||||
* @param event click event
|
||||
*/
|
||||
window.lam.webauthn.removeDevice = function(event) {
|
||||
event.preventDefault();
|
||||
const element = jQuery(event.target);
|
||||
window.lam.webauthn.removeDeviceDialog(element, 'webauthnDevices');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user's own webauthn device.
|
||||
*
|
||||
* @param event click event
|
||||
*/
|
||||
window.lam.webauthn.removeOwnDevice = function(event) {
|
||||
event.preventDefault();
|
||||
const element = jQuery(event.target);
|
||||
window.lam.webauthn.removeDeviceDialog(element, 'webauthnOwnDevices');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the remove device diaog.
|
||||
*
|
||||
* @param element delete button
|
||||
* @param action action for request (delete|deleteOwn)
|
||||
*/
|
||||
window.lam.webauthn.removeDeviceDialog = function(element, action) {
|
||||
const dialogTitle = element.data('dialogtitle');
|
||||
const okText = element.data('oktext');
|
||||
const cancelText = element.data('canceltext');
|
||||
let buttonList = {};
|
||||
buttonList[okText] = function() {
|
||||
jQuery('#webauthnDeleteConfirm').dialog('close');
|
||||
window.lam.webauthn.sendRemoveDeviceRequest(element);
|
||||
window.lam.webauthn.sendRemoveDeviceRequest(element, action);
|
||||
};
|
||||
buttonList[cancelText] = function() {
|
||||
jQuery(this).dialog("close");
|
||||
|
@ -1604,16 +1627,15 @@ window.lam.webauthn.removeDevice = function(event) {
|
|||
buttons: buttonList,
|
||||
width: 'auto'
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the remove request to server.
|
||||
*
|
||||
* @param element button element
|
||||
* @param action action (delete|deleteOwn)
|
||||
*/
|
||||
window.lam.webauthn.sendRemoveDeviceRequest = function(element) {
|
||||
window.lam.webauthn.sendRemoveDeviceRequest = function(element, action) {
|
||||
const dn = element.data('dn');
|
||||
const credential = element.data('credential');
|
||||
const resultDiv = jQuery('#webauthn_results');
|
||||
|
@ -1626,7 +1648,7 @@ window.lam.webauthn.sendRemoveDeviceRequest = function(element) {
|
|||
credentialId: credential
|
||||
};
|
||||
jQuery.ajax({
|
||||
url: '../misc/ajax.php?function=webauthnDevices',
|
||||
url: '../misc/ajax.php?function=' + action,
|
||||
method: 'POST',
|
||||
data: data
|
||||
})
|
||||
|
|
|
@ -15,7 +15,7 @@ use \LAMCfgMain;
|
|||
/*
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2011 - 2019 Roland Gruber
|
||||
Copyright (C) 2011 - 2020 Roland Gruber
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -159,6 +159,9 @@ class Ajax {
|
|||
ob_end_clean();
|
||||
echo $jsonOut;
|
||||
}
|
||||
elseif ($function === 'webauthnOwnDevices') {
|
||||
$this->manageWebauthnOwnDevices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,7 +258,7 @@ class Ajax {
|
|||
private function manageWebauthnDevicesSearch($searchTerm) {
|
||||
include_once __DIR__ . '/../../lib/webauthn.inc';
|
||||
$database = new \LAM\LOGIN\WEBAUTHN\PublicKeyCredentialSourceRepositorySQLite();
|
||||
$results = $database->searchDevices($searchTerm);
|
||||
$results = $database->searchDevices('%' . $searchTerm . '%');
|
||||
$row = new htmlResponsiveRow();
|
||||
$row->addVerticalSpacer('0.5rem');
|
||||
if (empty($results)) {
|
||||
|
@ -326,6 +329,23 @@ class Ajax {
|
|||
echo json_encode(array('content' => $content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages requests to setup user's own webauthn devices.
|
||||
*/
|
||||
private function manageWebauthnOwnDevices() {
|
||||
$action = $_POST['action'];
|
||||
$dn = $_POST['dn'];
|
||||
$sessionDn = $_SESSION['ldap']->getUserName();
|
||||
if ($sessionDn !== $dn) {
|
||||
logNewMessage(LOG_ERR, 'Webauthn delete canceled, DN does not match.');
|
||||
die();
|
||||
}
|
||||
if ($action === 'delete') {
|
||||
$credentialId = $_POST['credentialId'];
|
||||
$this->manageWebauthnDevicesDelete($dn, $credentialId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles DN selection fields.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
namespace LAM\TOOLS\WEBAUTHN;
|
||||
use \htmlButton;
|
||||
use htmlDiv;
|
||||
use htmlGroup;
|
||||
use \htmlOutputText;
|
||||
use \htmlResponsiveRow;
|
||||
use \htmlResponsiveTable;
|
||||
use \htmlStatusMessage;
|
||||
use \htmlTitle;
|
||||
use \LAM\LOGIN\WEBAUTHN\PublicKeyCredentialSourceRepositorySQLite;
|
||||
|
||||
/*
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2020 Roland Gruber
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows webauthn device management.
|
||||
*
|
||||
* @author Roland Gruber
|
||||
* @package tools
|
||||
*/
|
||||
|
||||
/** security functions */
|
||||
include_once(__DIR__ . "/../../lib/security.inc");
|
||||
/** access to configuration options */
|
||||
include_once(__DIR__ . "/../../lib/config.inc");
|
||||
/** webauthn */
|
||||
include_once __DIR__ . '/../../lib/webauthn.inc';
|
||||
|
||||
// start session
|
||||
startSecureSession();
|
||||
enforceUserIsLoggedIn();
|
||||
|
||||
checkIfToolIsActive('toolWebauthn');
|
||||
|
||||
setlanguage();
|
||||
|
||||
include __DIR__ . '/../../lib/adminHeader.inc';
|
||||
echo '<div class="user-bright smallPaddingContent">';
|
||||
echo "<form action=\"webauthn.php\" method=\"post\">\n";
|
||||
$tabindex = 1;
|
||||
$container = new htmlResponsiveRow();
|
||||
|
||||
$container->add(new htmlTitle(_("Webauthn devices")), 12);
|
||||
|
||||
$userDn = $_SESSION['ldap']->getUserName();
|
||||
$database = new PublicKeyCredentialSourceRepositorySQLite();
|
||||
$results = $database->searchDevices($userDn);
|
||||
$container->addVerticalSpacer('0.5rem');
|
||||
$buttonGroup = new htmlGroup();
|
||||
$reloadButton = new htmlButton('reload', _('Reload'));
|
||||
$reloadButton->setIconClass('refreshButton');
|
||||
$buttonGroup->addElement($reloadButton);
|
||||
$container->add($buttonGroup, 12);
|
||||
$container->addVerticalSpacer('2rem');
|
||||
if (empty($results)) {
|
||||
$container->add(new htmlStatusMessage('INFO', _('No devices found.')), 12);
|
||||
}
|
||||
else {
|
||||
$titles = array(
|
||||
_('Registration'),
|
||||
_('Last use'),
|
||||
_('Delete')
|
||||
);
|
||||
$data = array();
|
||||
$id = 0;
|
||||
foreach ($results as $result) {
|
||||
$delButton = new htmlButton('deleteDevice' . $id, 'delete.png', true);
|
||||
$delButton->addDataAttribute('credential', $result['credentialId']);
|
||||
$delButton->addDataAttribute('dn', $result['dn']);
|
||||
$delButton->addDataAttribute('dialogtitle', _('Remove device'));
|
||||
$delButton->addDataAttribute('oktext', _('Ok'));
|
||||
$delButton->addDataAttribute('canceltext', _('Cancel'));
|
||||
$delButton->setOnClick('window.lam.webauthn.removeOwnDevice(event);');
|
||||
$data[] = array(
|
||||
new htmlOutputText(date('Y-m-d H:i:s', $result['registrationTime'])),
|
||||
new htmlOutputText(date('Y-m-d H:i:s', $result['lastUseTime'])),
|
||||
$delButton
|
||||
);
|
||||
$id++;
|
||||
}
|
||||
$table = new htmlResponsiveTable($titles, $data);
|
||||
$tableDiv = new htmlDiv('webauthn_results', $table);
|
||||
$tableDiv->addDataAttribute('sec_token_value', getSecurityTokenValue());
|
||||
$container->add($tableDiv, 12);
|
||||
}
|
||||
$container->addVerticalSpacer('2rem');
|
||||
|
||||
$confirmationDiv = new htmlDiv('webauthnDeleteConfirm', new htmlOutputText(_('Do you really want to remove this device?')), array('hidden'));
|
||||
$container->add($confirmationDiv, 12);
|
||||
|
||||
|
||||
parseHtml(null, $container, array(), false, $tabindex, 'user');
|
||||
|
||||
echo '</form>';
|
||||
echo '</div>';
|
||||
include __DIR__ . '/../../lib/adminFooter.inc';
|
||||
|
||||
?>
|
|
@ -148,8 +148,9 @@ class PublicKeyCredentialSourceRepositorySQLiteTest extends TestCase {
|
|||
"uh1",
|
||||
1);
|
||||
$this->database->saveCredentialSource($source1);
|
||||
$this->assertNotEmpty($this->database->searchDevices('h1'));
|
||||
$this->assertEmpty($this->database->searchDevices('h2'));
|
||||
$this->assertNotEmpty($this->database->searchDevices('uh1'));
|
||||
$this->assertNotEmpty($this->database->searchDevices('%h1%'));
|
||||
$this->assertEmpty($this->database->searchDevices('uh2'));
|
||||
}
|
||||
|
||||
public function test_deleteDevice() {
|
||||
|
|
Loading…
Reference in New Issue