This commit is contained in:
Roland Gruber 2019-11-25 21:07:23 +01:00
parent 9637c2dff6
commit 1535bf4da6
7 changed files with 79 additions and 25 deletions

View File

@ -329,6 +329,8 @@ $helpArray = array (
"Text" => _('This text is displayed as footer on the self service main page.')),
"528" => array ("Headline" => _('User name attribute'),
"Text" => _('The attribute (e.g. "uid") that contains the user name for the 2-factor service.')),
"529" => array ("Headline" => _('Domain'),
"Text" => _('Please enter the webauthn domain. This is the public domain of the webserver (e.g. "example.com"). Do not include protocol or port.')),
"550" => array ("Headline" => _("From address"),
"Text" => _("This email address will be set as sender address of all password mails. If empty the system default (php.ini) will be used.")),
"551" => array ("Headline" => _("Subject"),

View File

@ -607,6 +607,7 @@ class LAMConfig {
private $twoFactorAuthenticationURL = 'https://localhost';
private $twoFactorAuthenticationClientId = null;
private $twoFactorAuthenticationSecretKey = null;
private $twoFactorAuthenticationDomain = null;
private $twoFactorAuthenticationInsecure = false;
private $twoFactorAuthenticationLabel = null;
private $twoFactorAuthenticationOptional = false;
@ -625,7 +626,7 @@ class LAMConfig {
'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL',
'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional',
'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey',
'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay'
'twoFactorAuthenticationDomain', 'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay'
);
@ -991,6 +992,9 @@ class LAMConfig {
if (!in_array("twoFactorAuthenticationSecretKey", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationSecretKey: " . $this->twoFactorAuthenticationSecretKey . "\n");
}
if (!in_array("twoFactorAuthenticationDomain", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationDomain: " . $this->twoFactorAuthenticationDomain . "\n");
}
if (!in_array("twoFactorAuthenticationInsecure", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationInsecure: " . $this->twoFactorAuthenticationInsecure . "\n");
}
@ -2416,6 +2420,24 @@ class LAMConfig {
return $this->twoFactorAuthenticationSecretKey;
}
/**
* Sets the domain.
*
* @param string $domain domain
*/
public function setTwoFactorAuthenticationDomain($domain) {
$this->twoFactorAuthenticationDomain = $domain;
}
/**
* Returns the domain.
*
* @return string domain
*/
public function getTwoFactorAuthenticationDomain() {
return $this->twoFactorAuthenticationDomain;
}
/**
* Returns if SSL certificate verification is turned off.
*

View File

@ -51,10 +51,11 @@ function isRegistered($dn) {
* Returns a challenge for a new token.
*
* @param string $dn DN
* @param bool $isSelfService is executed in self service
* @return PublicKeyCredentialCreationOptions challenge
*/
function getRegistrationObject($dn) {
$rpEntity = createRpEntry();
function getRegistrationObject($dn, $isSelfService) {
$rpEntity = createRpEntry($isSelfService);
$userEntity = getUserEntity($dn);
$challenge = generateRandomPassword(32);
$credentialParameters = getCredentialParameters();
@ -76,13 +77,19 @@ function getRegistrationObject($dn) {
/**
* Returns the part that identifies the server and application.
*
* @param bool $isSelfService is executed in self service
* @return PublicKeyCredentialRpEntity relying party entry
*/
function createRpEntry() {
function createRpEntry($isSelfService) {
$pathPrefix = $isSelfService ? '../' : '';
$icon = $pathPrefix . '../graphics/logo136.png';
if (!$isSelfService) {
$domain = $_SESSION['config']->getTwoFactorAuthenticationDomain();
}
return new PublicKeyCredentialRpEntity(
'LDAP Account Manager', //Name
null, // TODO check if domain is required
null // TODO icon
$domain,
$icon
);
}

View File

@ -473,21 +473,22 @@ if (extension_loaded('curl')) {
$twoFactorSelect = new htmlResponsiveSelect('twoFactor', $twoFactorOptions, array($conf->getTwoFactorAuthentication()), _('Provider'), '514');
$twoFactorSelect->setHasDescriptiveElements(true);
$twoFactorSelect->setTableRowsToHide(array(
TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURLs', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURLs', 'twoFactorOptional', 'twoFactorInsecure', 'twoFactorLabel'),
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute', 'twoFactorDomain'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURLs', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorDomain'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorAttribute', 'twoFactorDomain'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURLs', 'twoFactorOptional', 'twoFactorInsecure', 'twoFactorLabel', 'twoFactorDomain'),
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorURL', 'twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
));
$twoFactorSelect->setTableRowsToShow(array(
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURL', 'twoFactorLabel',
'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURLs', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_DUO => array('twoFactorURL', 'twoFactorLabel',
'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_WEBAUTHN => array('twoFactorDomain')
));
$row->add($twoFactorSelect, 12);
$twoFactorAttribute = new htmlResponsiveInputField(_("User name attribute"), 'twoFactorAttribute', $conf->getTwoFactorAuthenticationAttribute(), '528');
@ -500,8 +501,10 @@ if (extension_loaded('curl')) {
$row->add($twoFactorUrl, 12);
$twoFactorClientId = new htmlResponsiveInputField(_("Client id"), 'twoFactorClientId', $conf->getTwoFactorAuthenticationClientId(), '524');
$row->add($twoFactorClientId, 12);
$twoFactorSecretKey = new htmlResponsiveInputField(_("Secret key"), 'twoFactorSecretKey', $conf->getTwoFactorAuthenticationSecretKey(), '525');
$twoFactorSecretKey = new htmlResponsiveInputField(_("Secret key"), 'twoFactorSecretKey', $conf->getTwoFactorAuthenticationSecretKey(), '528');
$row->add($twoFactorSecretKey, 12);
$twoFactorDomain = new htmlResponsiveInputField(_("Domain"), 'twoFactorDomain', $conf->getTwoFactorAuthenticationDomain(), '529');
$row->add($twoFactorDomain, 12);
$twoFactorLabel = new htmlResponsiveInputField(_("Label"), 'twoFactorLabel', $conf->getTwoFactorAuthenticationLabel(), '517');
$row->add($twoFactorLabel, 12);
$row->add(new htmlResponsiveInputCheckbox('twoFactorOptional', $conf->getTwoFactorAuthenticationOptional(), _('Optional'), '519'), 12);
@ -741,6 +744,7 @@ function checkInput() {
}
$conf->setTwoFactorAuthenticationClientId($_POST['twoFactorClientId']);
$conf->setTwoFactorAuthenticationSecretKey($_POST['twoFactorSecretKey']);
$conf->setTwoFactorAuthenticationDomain($_POST['twoFactorDomain']);
$conf->setTwoFactorAuthenticationInsecure(isset($_POST['twoFactorInsecure']) && ($_POST['twoFactorInsecure'] == 'on'));
$conf->setTwoFactorAuthenticationLabel($_POST['twoFactorLabel']);
$conf->setTwoFactorAuthenticationOptional(isset($_POST['twoFactorOptional']) && ($_POST['twoFactorOptional'] == 'on'));

View File

@ -1411,19 +1411,17 @@ window.lam.webauthn.run = function(prefix) {
* @param publicKey registration object
*/
window.lam.webauthn.register = function(publicKey) {
console.log(publicKey);
publicKey.challenge = Uint8Array.from(window.atob(publicKey.challenge), c=>c.charCodeAt(0));
publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), c=>c.charCodeAt(0));
navigator.credentials.create({publicKey})
.then(function (data) {
console.log(data);
let publicKeyCredential = {
id: data.id,
type: data.type,
rawId: btoa(String.fromCharCode(new Uint8Array(data.rawId))),
response: {
clientDataJSON: btoa(String.fromCharCode((new Uint8Array(data.response.clientDataJSON)))),
attestationObject: btoa(String.fromCharCode((new Uint8Array(data.response.attestationObject))))
clientDataJSON: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
attestationObject: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.attestationObject))
}
};
console.log(publicKeyCredential);
@ -1433,6 +1431,16 @@ window.lam.webauthn.register = function(publicKey) {
});
}
/**
* Converts an array to a base64 string.
*
* @param input array
* @returns base64 string
*/
window.lam.webauthn.arrayToBase64String = function(input) {
return btoa(String.fromCharCode(...input));
}
jQuery(document).ready(function() {
window.lam.gui.equalHeight();
window.lam.form.autoTrim();

View File

@ -196,7 +196,7 @@ class Ajax {
$userDN = $_SESSION['ldap']->getUserName();
$isRegistered = isRegistered($userDN);
if (!$isRegistered) {
$registrationObject = getRegistrationObject($userDN);
$registrationObject = getRegistrationObject($userDN, $isSelfService);
echo json_encode(
array(
'action' => 'register',

View File

@ -565,6 +565,17 @@ class LAMConfigTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationSecretKey());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationDomain() and LAMConfig->setTwoFactorAuthenticationDomain()
*/
public function testTwoFactorAuthenticationDomain() {
$val = 'test.com';
$this->lAMConfig->setTwoFactorAuthenticationDomain($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationDomain());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationDomain());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationInsecure() and LAMConfig->setTwoFactorAuthenticationInsecure()
*/