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.')), "Text" => _('This text is displayed as footer on the self service main page.')),
"528" => array ("Headline" => _('User name attribute'), "528" => array ("Headline" => _('User name attribute'),
"Text" => _('The attribute (e.g. "uid") that contains the user name for the 2-factor service.')), "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"), "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.")), "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"), "551" => array ("Headline" => _("Subject"),

View File

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

View File

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

View File

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

View File

@ -1411,19 +1411,17 @@ window.lam.webauthn.run = function(prefix) {
* @param publicKey registration object * @param publicKey registration object
*/ */
window.lam.webauthn.register = function(publicKey) { window.lam.webauthn.register = function(publicKey) {
console.log(publicKey);
publicKey.challenge = Uint8Array.from(window.atob(publicKey.challenge), c=>c.charCodeAt(0)); 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)); publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), c=>c.charCodeAt(0));
navigator.credentials.create({publicKey}) navigator.credentials.create({publicKey})
.then(function (data) { .then(function (data) {
console.log(data);
let publicKeyCredential = { let publicKeyCredential = {
id: data.id, id: data.id,
type: data.type, type: data.type,
rawId: btoa(String.fromCharCode(new Uint8Array(data.rawId))), rawId: btoa(String.fromCharCode(new Uint8Array(data.rawId))),
response: { response: {
clientDataJSON: btoa(String.fromCharCode((new Uint8Array(data.response.clientDataJSON)))), clientDataJSON: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
attestationObject: btoa(String.fromCharCode((new Uint8Array(data.response.attestationObject)))) attestationObject: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.attestationObject))
} }
}; };
console.log(publicKeyCredential); 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() { jQuery(document).ready(function() {
window.lam.gui.equalHeight(); window.lam.gui.equalHeight();
window.lam.form.autoTrim(); window.lam.form.autoTrim();

View File

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

View File

@ -565,6 +565,17 @@ class LAMConfigTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationSecretKey()); $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() * Tests LAMConfig->getTwoFactorAuthenticationInsecure() and LAMConfig->setTwoFactorAuthenticationInsecure()
*/ */