webauthn
This commit is contained in:
parent
9637c2dff6
commit
1535bf4da6
|
@ -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"),
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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()
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue