diff --git a/lam/HISTORY b/lam/HISTORY
index 47ebe3aa..5ad4d74b 100644
--- a/lam/HISTORY
+++ b/lam/HISTORY
@@ -1,5 +1,6 @@
December 2018 6.6
- New import/export in tools menu
+ - YubiKey support
25.09.2018 6.5
diff --git a/lam/docs/manual-sources/chapter-modules.xml b/lam/docs/manual-sources/chapter-modules.xml
index 00263ab7..837d79fb 100644
--- a/lam/docs/manual-sources/chapter-modules.xml
+++ b/lam/docs/manual-sources/chapter-modules.xml
@@ -1992,6 +1992,74 @@ ldapsearch -x -h $server -p $port -b $baseDN -s sub "(&(objectclass=posixAcc
AuthorizedKeysCommandUser root
+
+ YubiKey
+
+ You can manage your YubiKey ids with LAM. It supports the yubiKeyUser schema
+ or any other attribute mapping.
+
+ Configuration
+
+ First, you need to activate the YubiKey module for users in your
+ LAM server profile.
+
+
+
+
+
+ Second, you need to specify which object class and attribute name
+ should be used.
+
+ Object class: If you have an object class just for the YubiKey ids
+ then enter it here. LAM will then provide options to add and remove it.
+ In case you reuse some existing attribute from e.g. inetOrgPerson please
+ leave object class name blank.
+
+ Attribute name: please enter the attribute name that is used for
+ the key ids.
+
+
+
+
+
+ You will then be able to manage the key ids for your users.
+
+
+
+
+
+ Self Service (LAM Pro)
+
+ This will allow your users to update their own keys.
+
+ You need to configure the object class and attribute name first.
+ This is done on tab "Module settings" in self service profile.
+
+ Attention: Please note that both
+ fields are mandatory here. Even if you reused an attribute from some
+ existing object class you need to set it here. LAM needs this to detect
+ if the user can add keys.
+
+
+
+
+
+ Then add the YubiKey ids field to your self service profile on tab
+ "Page layout".
+
+
+
+
+
+ When a user with the specified object class logs in then the key
+ input fields are shown.
+
+
+
+
+
+
Authorized services
diff --git a/lam/docs/manual-sources/images/mod_yubikey1.png b/lam/docs/manual-sources/images/mod_yubikey1.png
new file mode 100644
index 00000000..fddd5d7d
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey1.png differ
diff --git a/lam/docs/manual-sources/images/mod_yubikey2.png b/lam/docs/manual-sources/images/mod_yubikey2.png
new file mode 100644
index 00000000..0cf49c3e
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey2.png differ
diff --git a/lam/docs/manual-sources/images/mod_yubikey3.png b/lam/docs/manual-sources/images/mod_yubikey3.png
new file mode 100644
index 00000000..acd5c378
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey3.png differ
diff --git a/lam/docs/manual-sources/images/mod_yubikey4.png b/lam/docs/manual-sources/images/mod_yubikey4.png
new file mode 100644
index 00000000..c1439fc7
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey4.png differ
diff --git a/lam/docs/manual-sources/images/mod_yubikey5.png b/lam/docs/manual-sources/images/mod_yubikey5.png
new file mode 100644
index 00000000..eac43233
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey5.png differ
diff --git a/lam/docs/manual-sources/images/mod_yubikey6.png b/lam/docs/manual-sources/images/mod_yubikey6.png
new file mode 100644
index 00000000..02b94efc
Binary files /dev/null and b/lam/docs/manual-sources/images/mod_yubikey6.png differ
diff --git a/lam/graphics/yubikey.png b/lam/graphics/yubikey.png
new file mode 100755
index 00000000..bcd4d48c
Binary files /dev/null and b/lam/graphics/yubikey.png differ
diff --git a/lam/lib/baseModule.inc b/lam/lib/baseModule.inc
index 9b948af0..2f2bd6af 100644
--- a/lam/lib/baseModule.inc
+++ b/lam/lib/baseModule.inc
@@ -68,7 +68,10 @@ abstract class baseModule {
/** configuration settings of all modules */
protected $moduleSettings;
- /** self service profile with settings of all modules */
+ /**
+ * self service profile with settings of all modules
+ * @var selfServiceProfile profile
+ */
protected $selfServiceSettings;
/** name of parent accountContainer ($_SESSION[$base]) */
diff --git a/lam/lib/modules/yubiKeyUser.inc b/lam/lib/modules/yubiKeyUser.inc
new file mode 100644
index 00000000..06439c4c
--- /dev/null
+++ b/lam/lib/modules/yubiKeyUser.inc
@@ -0,0 +1,592 @@
+autoAddObjectClasses = false;
+ }
+
+ /**
+ * Returns true if this module can manage accounts of the current type, otherwise false.
+ *
+ * @return boolean true if module fits
+ */
+ public function can_manage() {
+ return in_array($this->get_scope(), array('user'));
+ }
+
+ /**
+ * Returns meta data that is interpreted by parent class
+ *
+ * @return array array with meta data
+ *
+ * @see baseModule::get_metaData()
+ */
+ public function get_metaData() {
+ $return = array();
+ // icon
+ $return['icon'] = 'yubikey.png';
+ // alias name
+ $return["alias"] = _("YubiKey");
+ // module dependencies
+ $return['dependencies'] = array('depends' => array(), 'conflicts' => array());
+ // managed object classes
+ $objectClass = $this->getObjectClassName();
+ if (!empty($objectClass)) {
+ $return['objectClasses'] = array($objectClass);
+ }
+ // managed attributes
+ $attributeName = $this->getAttributeName();
+ $return['attributes'] = array($attributeName);
+ // help Entries
+ $return['help'] = array(
+ $attributeName => array(
+ "Headline" => _("YubiKey ids"), 'attr' => $attributeName,
+ "Text" => _("Please enter your YubiKey ids.")
+ ),
+ 'keyList' => array(
+ "Headline" => _("YubiKey ids"), 'attr' => $attributeName,
+ "Text" => _("Please a comma separated list of your YubiKey ids.")
+ ),
+ 'objectClass' => array(
+ "Headline" => _("Object class"),
+ "Text" => _("Please enter the object class that should be used for YubiKey (e.g. 'yubiKeyUser').")
+ ),
+ 'attributeName' => array(
+ "Headline" => _("Attribute name"),
+ "Text" => _("Please enter the attribute name that should be used for YubiKey (e.g. 'yubiKeyId').")
+ ),
+ );
+ // upload fields
+ $return['upload_columns'] = array(
+ array(
+ 'name' => 'yubiKeyUser_yubiKeyId',
+ 'description' => _('YubiKey ids'),
+ 'help' => 'keyList',
+ 'example' => 'abcd1234, vwyxz12345'
+ )
+ );
+ // available PDF fields
+ $return['PDF_fields'] = array(
+ 'yubiKeyId' => _('YubiKey ids')
+ );
+ // self service field settings
+ $return['selfServiceFieldSettings'] = array(
+ 'yubiKeyId' => _('YubiKey ids'),
+ );
+ $return['selfServiceReadOnlyFields'] = array('yubiKeyId');
+ return $return;
+ }
+
+ /**
+ * This function fills the message array.
+ **/
+ protected function load_Messages() {
+ $this->messages['yubiKeyId'][0] = array('ERROR', _('Please enter a valid key id.'));
+ $this->messages['yubiKeyId'][1] = array('ERROR', _('Account %s:') . ' yubiKeyUser_yubiKeyId', _('Please enter a valid key id.'));
+ }
+
+ /**
+ * Returns the HTML meta data for the main account page.
+ *
+ * @return htmlElement HTML meta data
+ */
+ public function display_html_attributes() {
+ $return = new htmlTable();
+ $objectClass = $this->getObjectClassName();
+ $attributeName = $this->getAttributeName();
+ if (empty($attributeName)) {
+ $message = new htmlStatusMessage('ERROR', _('Invalid configuration detected. Please edit your server profile (module settings) and fill all required fields.'));
+ $return->addElement($message, true);
+ return $return;
+ }
+ if (empty($objectClass) || in_array($objectClass, $this->attributes['objectClass'])) {
+ $this->addMultiValueInputTextField($return, $attributeName, _('YubiKey ids'), false, '256', false, null, '50');
+ if (!empty($objectClass)) {
+ $return->addElement(new htmlSpacer(null, '30px'), true);
+
+ $remButton = new htmlButton('remObjectClass', _('Remove YubiKey extension'));
+ $remButton->colspan = 3;
+ $return->addElement($remButton);
+ }
+ }
+ else {
+ $return->addElement(new htmlButton('addObjectClass', _('Add YubiKey extension')));
+ }
+ return $return;
+ }
+
+ /**
+ * Processes user input of the primary module page.
+ * It checks if all input values are correct and updates the associated LDAP attributes.
+ *
+ * @return array list of info/error messages
+ */
+ public function process_attributes() {
+ $messages = array();
+ $objectClass = $this->getObjectClassName();
+ $attributeName = $this->getAttributeName();
+ // add extension
+ if (isset($_POST['addObjectClass'])) {
+ $this->attributes['objectClass'][] = $objectClass;
+ return array();
+ }
+ // remove extension
+ elseif (isset($_POST['remObjectClass'])) {
+ $this->attributes['objectClass'] = array_delete(array($objectClass), $this->attributes['objectClass']);
+ if (!empty($this->attributes[$attributeName])) {
+ unset($this->attributes[$attributeName]);
+ }
+ return array();
+ }
+ // skip processing if extension is not active
+ if (!empty($objectClass) && !in_array($objectClass, $this->attributes['objectClass'])) {
+ return array();
+ }
+ $this->processMultiValueInputTextField($attributeName, $messages, 'ascii');
+ $this->attributes[$attributeName] = array_values(array_unique($this->attributes[$attributeName]));
+ return $messages;
+ }
+
+ /**
+ * Returns a list of modifications which have to be made to the LDAP account.
+ *
+ * @return array list of modifications
+ *
This function returns an array with 3 entries:
+ *
array( DN1 ('add' => array($attr), 'remove' => array($attr), 'modify' => array($attr)), DN2 .... )
+ *
DN is the DN to change. It may be possible to change several DNs (e.g. create a new user and add him to some groups via attribute memberUid)
+ *
"add" are attributes which have to be added to LDAP entry
+ *
"remove" are attributes which have to be removed from LDAP entry
+ *
"modify" are attributes which have to been modified in LDAP entry
+ *
"info" are values with informational value (e.g. to be used later by pre/postModify actions)
+ */
+ public function save_attributes() {
+ $objectClass = $this->getObjectClassName();
+ if (!empty($objectClass) && !in_array($objectClass, $this->attributes['objectClass']) && !in_array($objectClass, $this->orig['objectClass'])) {
+ // skip saving if the extension was not added/modified
+ return array();
+ }
+ return parent::save_attributes();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see baseModule::build_uploadAccounts()
+ */
+ public function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules, &$type) {
+ $objectClass = $this->getObjectClassName();
+ $attributeName = $this->getAttributeName();
+ $messages = array();
+ for ($i = 0; $i < sizeof($rawAccounts); $i++) {
+ // add object class
+ if (!empty($objectClass) && !in_array($objectClass, $partialAccounts[$i]['objectClass'])) {
+ $partialAccounts[$i]['objectClass'][] = $objectClass;
+ }
+ // add keys
+ $message = $this->messages['yubiKeyId'][1];
+ $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'yubiKeyUser_yubiKeyId', $attributeName, 'ascii', $message, $messages, '/,[ ]*/');
+ }
+ return $messages;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see baseModule::get_pdfEntries()
+ */
+ public function get_pdfEntries($pdfKeys, $typeId) {
+ $return = array();
+ $attributeName = $this->getAttributeName();
+ if (!empty($this->attributes[$attributeName])) {
+ $pdfTable = new PDFTable(_('YubiKey ids'));
+ for ($i = 0; $i < sizeof($this->attributes[$attributeName]); $i++) {
+ $pdfRow = new PDFTableRow();
+ $pdfRow->cells[] = new PDFTableCell($this->attributes[$attributeName][$i]);
+ $pdfTable->rows[] = $pdfRow;
+ }
+ $this->addPDFTable($return, 'yubiKeyId', $pdfTable);
+ }
+ return $return;
+ }
+
+ /**
+ * Returns the meta HTML code for each input field.
+ * format: array( => array(), ...)
+ * It is not possible to display help links.
+ *
+ * @param array $fields list of active fields
+ * @param array $attributes attributes of LDAP account
+ * @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable
+ * @param array $readOnlyFields list of read-only fields
+ * @return array list of meta HTML elements (field name => htmlResponsiveRow)
+ */
+ public function getSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
+ $return = array();
+ if ($passwordChangeOnly) {
+ return $return; // no fields as long no LDAP content can be read
+ }
+ $attributes = array_change_key_case($attributes, CASE_LOWER);
+ $objectClass = strtolower($this->getObjectClassName());
+ if (!in_array_ignore_case($objectClass, $attributes['objectclass'])) {
+ return $return;
+ }
+ if (in_array('yubiKeyId', $fields)) {
+ $attributeName = strtolower($this->getAttributeName());
+ $keyIds = array();
+ if (isset($attributes[$attributeName][0])) {
+ $keyIds = $attributes[$attributeName];
+ }
+ $_SESSION[self::SESS_KEY_LIST] = $keyIds;
+ $keyTable = new htmlTable();
+ // JavaScript functions
+ $keyTable->addElement($this->getSelfServiceKeysJSBlock(), true);
+ // input fields
+ $keyTable->addElement(new htmlDiv('yubiKeyIdDiv', $this->getSelfServiceKeys()), true);
+ $keyLabel = new htmlOutputText($this->getSelfServiceLabel('yubiKeyId', _('YubiKey ids')));
+ $row = new htmlResponsiveRow();
+ $row->addLabel($keyLabel);
+ $row->addField($keyTable);
+ $return['yubiKeyId'] = $row;
+ }
+ return $return;
+ }
+
+ /**
+ * Returns the meta HTML code to display the key area.
+ * This also includes the file upload.
+ *
+ * @return htmlTable key content
+ */
+ private function getSelfServiceKeys() {
+ $keys = $_SESSION[self::SESS_KEY_LIST];
+ $content = new htmlResponsiveRow();
+ if (sizeof($keys) > 0) {
+ for ($i = 0; $i < sizeof($keys); $i++) {
+ $group = new htmlGroup();
+ $keyInput = new htmlInputField('yubiKeyId_' . $i, $keys[$i]);
+ $keyInput->setFieldMaxLength(16384);
+ $group->addElement($keyInput);
+ $delLink = new htmlLink('', '#', '../../graphics/del.png');
+ $delLink->setTitle(_('Delete'));
+ $delLink->setOnClick('yubiKeyIdDeleteKey(' . $i . ', ' . sizeof($keys) . ');return false;');
+ $group->addElement($delLink);
+ if ($i == (sizeof($keys) - 1)) {
+ $addLink = new htmlLink('', '#', '../../graphics/add.png');
+ $addLink->setTitle(_('Add'));
+ $addLink->setOnClick('yubiKeyIdAddKey(' . sizeof($keys) . ');return false;');
+ $group->addElement($addLink);
+ }
+ $content->add($group, 12, 12, 12, 'nowrap');
+ }
+ }
+ else {
+ $addLink = new htmlLink('', '#', '../../graphics/add.png');
+ $addLink->setTitle(_('Add'));
+ $addLink->setOnClick('yubiKeyIdAddKey(' . sizeof($keys) . ');return false;');
+ $content->add($addLink, 12);
+ }
+ return $content;
+ }
+
+ /**
+ * Returns the Java Script functions to manage the keys.
+ *
+ * @return htmlJavaScript JS block
+ */
+ private static function getSelfServiceKeysJSBlock() {
+ $content = '
+ function yubiKeyIdDeleteKey(id, count) {
+ var actionJSON = {
+ "action": "deleteKey",
+ "id": id
+ };
+ for (c = 0; c < count; c++) {
+ actionJSON["yubiKeyId_" + c] = jQuery(\'#yubiKeyId_\' + c).val();
+ }
+ var data = {jsonInput: actionJSON};
+ data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
+ jQuery.post(\'../misc/ajax.php?selfservice=1&module=yubiKeyUser&scope=user\',
+ data, function(data) {yubiKeyIdDeleteKeyHandleReply(data);}, \'json\');
+ }
+
+ function yubiKeyIdDeleteKeyHandleReply(data) {
+ if (data.errorsOccured == "false") {
+ jQuery(\'#yubiKeyIdDiv\').html(data.html);
+ }
+ else {
+ alert(data.errormessage);
+ }
+ }
+
+ function yubiKeyIdAddKey(count) {
+ var actionJSON = {
+ "action": "addKey"
+ };
+ for (c = 0; c < count; c++) {
+ actionJSON["yubiKeyId_" + c] = jQuery(\'#yubiKeyId_\' + c).val();
+ }
+ var data = {jsonInput: actionJSON};
+ data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
+ jQuery.post(\'../misc/ajax.php?selfservice=1&module=yubiKeyUser&scope=user'
+ . '&' . getSecurityTokenName() . '=' . getSecurityTokenValue()
+ . '\', data, function(data) {yubiKeyIdAddKeyHandleReply(data);}, \'json\');
+ }
+
+ function yubiKeyIdAddKeyHandleReply(data) {
+ if (data.errorsOccured == "false") {
+ jQuery(\'#yubiKeyIdDiv\').html(data.html);
+ }
+ else {
+ alert(data.errormessage);
+ }
+ }
+
+ ';
+ return new htmlJavaScript($content);
+ }
+
+ /**
+ * Checks if all input values are correct and returns the LDAP attributes which should be changed.
+ *
Return values:
+ *
messages: array of parameters to create status messages
+ *
add: array of attributes to add
+ *
del: array of attributes to remove
+ *
mod: array of attributes to modify
+ *
info: array of values with informational value (e.g. to be used later by pre/postModify actions)
+ *
+ * Calling this method does not require the existence of an enclosing {@link accountContainer}.
+ *
+ * @param string $fields input fields
+ * @param array $attributes LDAP attributes
+ * @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable
+ * @param array $readOnlyFields list of read-only fields
+ * @return array messages and attributes (array('messages' => array(), 'add' => array('mail' => array('test@test.com')), 'del' => array(), 'mod' => array(), 'info' => array()))
+ */
+ public function checkSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
+ $return = array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array(), 'info' => array());
+ if ($passwordChangeOnly) {
+ return $return; // skip processing if only a password change is done
+ }
+ $attributes = array_change_key_case($attributes, CASE_LOWER);
+ $objectClass = strtolower($this->getObjectClassName());
+ if (!in_array_ignore_case($objectClass, $attributes['objectclass'])) {
+ return $return;
+ }
+ if (in_array('yubiKeyId', $fields)) {
+ $attributeName = strtolower($this->getAttributeName());
+ $newKeys = array();
+ $counter = 0;
+ while (isset($_POST['yubiKeyId_' . $counter])) {
+ $newKeys[] = $_POST['yubiKeyId_' . $counter];
+ $counter++;
+ }
+ $count = sizeof($newKeys);
+ for ($i = 0; $i < $count; $i++) {
+ if (trim($newKeys[$i]) == '') {
+ unset($newKeys[$i]);
+ }
+ elseif (!get_preg($newKeys[$i], 'ascii')) {
+ $return['messages'][] = array('ERROR', _('Please enter a valid key id.'), htmlspecialchars($newKeys[$i]));
+ }
+ }
+ $newKeys = array_values(array_unique($newKeys));
+ $oldKeys = array();
+ if (isset($attributes[$attributeName][0])) {
+ $oldKeys = $attributes[$attributeName];
+ }
+ $update = false;
+ if (sizeof($newKeys) != sizeof($oldKeys)) {
+ $update = true;
+ }
+ else {
+ for ($i = 0; $i < sizeof($newKeys); $i++) {
+ if (!in_array($newKeys[$i], $oldKeys)) {
+ $update = true;
+ break;
+ }
+ }
+ }
+ if ($update) {
+ if (sizeof($oldKeys) == 0) {
+ $return['add'][$attributeName] = $newKeys;
+ }
+ elseif (sizeof($newKeys) == 0) {
+ $return['del'][$attributeName] = $newKeys;
+ }
+ else {
+ $return['mod'][$attributeName] = $newKeys;
+ }
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Manages AJAX requests.
+ * This function may be called with or without an account container.
+ */
+ public function handleAjaxRequest() {
+ $jsonInput = $_POST['jsonInput'];
+ $jsonReturn = self::invalidAjaxRequest();
+ if (isset($jsonInput['action'])) {
+ if ($jsonInput['action'] == 'deleteKey') {
+ $jsonReturn = $this->ajaxDeleteSelfServiceKey($jsonInput);
+ }
+ elseif ($jsonInput['action'] == 'addKey') {
+ $_SESSION[self::SESS_KEY_LIST][] = '';
+ ob_start();
+ $contentElement = $this->getSelfServiceKeys();
+ ob_end_clean();
+ ob_start();
+ $tabindex = 999;
+ parseHtml(null, $contentElement, array(), true, $tabindex, $this->get_scope());
+ $content = ob_get_contents();
+ ob_end_clean();
+ $jsonReturn = array(
+ 'errorsOccured' => 'false',
+ 'html' => $content,
+ );
+ }
+ }
+ echo json_encode($jsonReturn);
+ }
+
+ /**
+ * Manages the deletion of a key.
+ *
+ * @param array $data JSON data
+ */
+ private function ajaxDeleteSelfServiceKey($data) {
+ if (!isset($data['id'])) {
+ return self::invalidAjaxRequest();
+ }
+ $index = $data['id'];
+ if (array_key_exists($index, $_SESSION[self::SESS_KEY_LIST])) {
+ unset($_SESSION[self::SESS_KEY_LIST][$index]);
+ $_SESSION[self::SESS_KEY_LIST] = array_values($_SESSION[self::SESS_KEY_LIST]);
+ }
+ ob_start();
+ $contentElement = $this->getSelfServiceKeys();
+ ob_end_clean();
+ ob_start();
+ $tabindex = 999;
+ parseHtml(null, $contentElement, array(), true, $tabindex, $this->get_scope());
+ $content = ob_get_contents();
+ ob_end_clean();
+ return array(
+ 'errorsOccured' => 'false',
+ 'html' => $content,
+ );
+ }
+
+ /**
+ * Invalid AJAX request received.
+ *
+ * @param String $message error message
+ */
+ public static function invalidAjaxRequest($message = null) {
+ if ($message == null) {
+ $message = _('Invalid request');
+ }
+ return array('errorsOccured' => 'true', 'errormessage' => $message);
+ }
+
+ /**
+ * Returns the object class used for YubiKey.
+ *
+ * @return string object class
+ */
+ private function getObjectClassName() {
+ if (!empty($this->moduleSettings['yubiKeyUser_objectClass'][0])) {
+ return $this->moduleSettings['yubiKeyUser_objectClass'][0];
+ }
+ elseif (!empty($this->selfServiceSettings->moduleSettings['yubiKeyUser_objectClass'][0])) {
+ return $this->selfServiceSettings->moduleSettings['yubiKeyUser_objectClass'][0];
+ }
+ return null;
+ }
+
+ /**
+ * Returns the attribute name used for YubiKey.
+ *
+ * @return string attribute name
+ */
+ private function getAttributeName() {
+ if (!empty($this->moduleSettings['yubiKeyUser_attributeName'][0])) {
+ return $this->moduleSettings['yubiKeyUser_attributeName'][0];
+ }
+ elseif (!empty($this->selfServiceSettings->moduleSettings['yubiKeyUser_attributeName'][0])) {
+ return $this->selfServiceSettings->moduleSettings['yubiKeyUser_attributeName'][0];
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see baseModule::get_configOptions()
+ */
+ public function get_configOptions($scopes, $allScopes) {
+ $configContainer = new htmlResponsiveRow();
+ $configContainer->add(new htmlResponsiveInputField(_('Object class'), 'yubiKeyUser_objectClass', null, 'objectClass'), 12);
+ $configContainer->add(new htmlResponsiveInputField(_('Attribute name'), 'yubiKeyUser_attributeName', 'yubiKeyId', 'attributeName', true), 12);
+ return $configContainer;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see baseModule::getSelfServiceSettings()
+ */
+ public function getSelfServiceSettings($profile) {
+ $container = new htmlResponsiveRow();
+ $container->add(new htmlResponsiveInputField(_('Object class'), 'yubiKeyUser_objectClass', null, array('objectClass', 'yubiKeyUser')), 12);
+ $container->add(new htmlResponsiveInputField(_('Attribute name'), 'yubiKeyUser_attributeName', 'yubiKeyId', array('attributeName', 'yubiKeyUser')), 12);
+ return $container;
+ }
+
+}
+
+
+?>