login attribute for 2-factor

This commit is contained in:
Roland Gruber 2019-08-11 09:39:47 +02:00
parent 5f15b2fae2
commit edb50f4d4b
13 changed files with 119 additions and 31 deletions

View File

@ -1,5 +1,6 @@
September 2019 6.9
- Group account types can show member+owner count in list view
- 2-factor authentication: user name attribute for privacyIDEA can be specified
- LAM Pro:
-> New self service settings for login and main page footer

View File

@ -636,6 +636,11 @@
<para>Base URL: please enter the URL of your privacyIDEA
instance</para>
</listitem>
<listitem>
<para>User name attribute: please enter the LDAP attribute name
that contains the user ID (e.g. "uid")</para>
</listitem>
</itemizedlist>
<para>YubiKey:</para>

View File

@ -334,6 +334,11 @@
<para>Base URL: please enter the URL of your privacyIDEA
instance</para>
</listitem>
<listitem>
<para>User name attribute: please enter the LDAP attribute name
that contains the user ID (e.g. "uid")</para>
</listitem>
</itemizedlist>
<para>YubiKey:</para>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -323,6 +323,8 @@ $helpArray = array (
"Text" => _('This text is displayed as footer on the self service login page.')),
"527" => array ("Headline" => _('Main page footer'),
"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.')),
"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

@ -53,8 +53,6 @@ interface TwoFactorProvider {
*/
public function verify2ndFactor($user, $password, $serial, $twoFactorInput);
}
/**
@ -79,8 +77,27 @@ class PrivacyIDEAProvider implements TwoFactorProvider {
*/
public function getSerials($user, $password) {
logNewMessage(LOG_DEBUG, 'PrivacyIDEAProvider: Getting serials for ' . $user);
$token = $this->authenticate($user, $password);
return $this->getSerialsForUser($user, $token);
$loginAttribute = $this->getLoginAttributeValue($user);
$token = $this->authenticate($loginAttribute, $password);
return $this->getSerialsForUser($loginAttribute, $token);
}
/**
* Returns the value of the user attribute in LDAP.
*
* @param string $userDn user DN
* @return string user name
*/
private function getLoginAttributeValue($userDn) {
$attrName = $this->config->twoFactorAuthenticationSerialAttributeName;
$userData = ldapGetDN($userDn, array($attrName));
if (empty($userData[$attrName])) {
return null;
}
if (is_array($userData[$attrName])) {
return $userData[$attrName][0];
}
return $userData[$attrName];
}
/**
@ -89,7 +106,8 @@ class PrivacyIDEAProvider implements TwoFactorProvider {
*/
public function verify2ndFactor($user, $password, $serial, $twoFactorInput) {
logNewMessage(LOG_DEBUG, 'PrivacyIDEAProvider: Checking 2nd factor for ' . $user);
$token = $this->authenticate($user, $password);
$loginAttribute = $this->getLoginAttributeValue($user);
$token = $this->authenticate($loginAttribute, $password);
return $this->verify($token, $serial, $twoFactorInput);
}
@ -360,6 +378,13 @@ class TwoFactorProviderService {
$tfConfig->twoFactorAuthenticationSerialAttributeName = 'yubiKeyId';
}
}
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) {
$attrName = $profile->twoFactorAuthenticationAttribute;
if (empty($attrName)) {
$attrName = 'uid';
}
$tfConfig->twoFactorAuthenticationSerialAttributeName = strtolower($attrName);
}
return $tfConfig;
}
@ -385,6 +410,9 @@ class TwoFactorProviderService {
$tfConfig->twoFactorAuthenticationSerialAttributeName = 'yubiKeyId';
}
}
if ($tfConfig->twoFactorAuthentication == TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA) {
$tfConfig->twoFactorAuthenticationSerialAttributeName = strtolower($conf->getTwoFactorAuthenticationAttribute());
}
return $tfConfig;
}

View File

@ -881,7 +881,7 @@ function searchLDAPPaged($server, $dn, $filter, $attributes, $attrsOnly, $limit)
*/
function ldapGetDN($dn, $attributes = array('dn'), $handle = null) {
if ($handle == null) {
$handle = $_SESSION['ldap']->server();
$handle = getLDAPServerHandle();
}
$return = null;
$sr = @ldap_read($handle, escapeDN($dn), 'objectClass=*', $attributes, 0, 0, 0, LDAP_DEREF_NEVER);

View File

@ -598,6 +598,7 @@ class LAMConfig {
private $twoFactorAuthenticationLabel = null;
private $twoFactorAuthenticationOptional = false;
private $twoFactorAuthenticationCaption = '';
private $twoFactorAuthenticationAttribute = '';
/** List of all settings in config file */
private $settings = array("ServerURL", "useTLS", "followReferrals", 'pagedResults', "Passwd", "Admins", "treesuffix",
@ -610,7 +611,8 @@ class LAMConfig {
'pwdResetAllowScreenPassword', 'pwdResetForcePasswordChange', 'pwdResetDefaultPasswordOutput',
'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL',
'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional',
'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey', 'referentialIntegrityOverlay'
'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey',
'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay'
);
@ -868,14 +870,33 @@ class LAMConfig {
if (!in_array("pwdResetAllowScreenPassword", $saved)) array_push($file_array, "\n" . "pwdResetAllowScreenPassword: " . $this->pwdResetAllowScreenPassword . "\n");
if (!in_array("pwdResetForcePasswordChange", $saved)) array_push($file_array, "\n" . "pwdResetForcePasswordChange: " . $this->pwdResetForcePasswordChange . "\n");
if (!in_array("pwdResetDefaultPasswordOutput", $saved)) array_push($file_array, "\n" . "pwdResetDefaultPasswordOutput: " . $this->pwdResetDefaultPasswordOutput . "\n");
if (!in_array("twoFactorAuthentication", $saved)) array_push($file_array, "\n" . "twoFactorAuthentication: " . $this->twoFactorAuthentication . "\n");
if (!in_array("twoFactorAuthenticationURL", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationURL: " . $this->twoFactorAuthenticationURL . "\n");
if (!in_array("twoFactorAuthenticationClientId", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationClientId: " . $this->twoFactorAuthenticationClientId . "\n");
if (!in_array("twoFactorAuthenticationSecretKey", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationSecretKey: " . $this->twoFactorAuthenticationSecretKey . "\n");
if (!in_array("twoFactorAuthenticationInsecure", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationInsecure: " . $this->twoFactorAuthenticationInsecure . "\n");
if (!in_array("twoFactorAuthenticationLabel", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationLabel: " . $this->twoFactorAuthenticationLabel . "\n");
if (!in_array("twoFactorAuthenticationOptional", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationOptional: " . $this->twoFactorAuthenticationOptional . "\n");
if (!in_array("twoFactorAuthenticationCaption", $saved)) array_push($file_array, "\n" . "twoFactorAuthenticationCaption: " . $this->twoFactorAuthenticationCaption . "\n");
if (!in_array("twoFactorAuthentication", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthentication: " . $this->twoFactorAuthentication . "\n");
}
if (!in_array("twoFactorAuthenticationURL", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationURL: " . $this->twoFactorAuthenticationURL . "\n");
}
if (!in_array("twoFactorAuthenticationClientId", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationClientId: " . $this->twoFactorAuthenticationClientId . "\n");
}
if (!in_array("twoFactorAuthenticationSecretKey", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationSecretKey: " . $this->twoFactorAuthenticationSecretKey . "\n");
}
if (!in_array("twoFactorAuthenticationInsecure", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationInsecure: " . $this->twoFactorAuthenticationInsecure . "\n");
}
if (!in_array("twoFactorAuthenticationLabel", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationLabel: " . $this->twoFactorAuthenticationLabel . "\n");
}
if (!in_array("twoFactorAuthenticationOptional", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationOptional: " . $this->twoFactorAuthenticationOptional . "\n");
}
if (!in_array("twoFactorAuthenticationCaption", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationCaption: " . $this->twoFactorAuthenticationCaption . "\n");
}
if (!in_array("twoFactorAuthenticationAttribute", $saved)) {
array_push($file_array, "\n" . "twoFactorAuthenticationAttribute: " . $this->twoFactorAuthenticationAttribute . "\n");
}
// check if all module settings were added
$m_settings = array_keys($this->moduleSettings);
for ($i = 0; $i < sizeof($m_settings); $i++) {
@ -2280,6 +2301,27 @@ class LAMConfig {
$this->twoFactorAuthenticationCaption = $twoFactorAuthenticationCaption;
}
/**
* Returns the user attribute.
*
* @return string user attribute
*/
public function getTwoFactorAuthenticationAttribute() {
if (empty($this->twoFactorAuthenticationAttribute)) {
return 'uid';
}
return $this->twoFactorAuthenticationAttribute;
}
/**
* Sets the user attribute.
*
* @param string $twoFactorAuthenticationAttribute user attribute
*/
public function setTwoFactorAuthenticationAttribute($twoFactorAuthenticationAttribute) {
$this->twoFactorAuthenticationAttribute = $twoFactorAuthenticationAttribute;
}
}

View File

@ -451,6 +451,7 @@ class selfServiceProfile {
public $twoFactorAuthenticationCaption = '';
public $twoFactorAuthenticationClientId = '';
public $twoFactorAuthenticationSecretKey = '';
public $twoFactorAuthenticationAttribute = 'uid';
/** provider for captcha (-/google) */
public $captchaProvider = '-';
@ -510,6 +511,7 @@ class selfServiceProfile {
$this->twoFactorAuthenticationCaption = '';
$this->twoFactorAuthenticationClientId = '';
$this->twoFactorAuthenticationSecretKey = '';
$this->twoFactorAuthenticationAttribute = 'uid';
$this->captchaProvider = '-';
$this->reCaptchaSiteKey = '';
$this->reCaptchaSecretKey = '';

View File

@ -466,16 +466,19 @@ if (extension_loaded('curl')) {
$twoFactorSelect->setHasDescriptiveElements(true);
$twoFactorSelect->setTableRowsToHide(array(
TwoFactorProviderService::TWO_FACTOR_NONE => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey')
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorClientId', 'twoFactorSecretKey'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorAttribute'),
));
$twoFactorSelect->setTableRowsToShow(array(
TwoFactorProviderService::TWO_FACTOR_PRIVACYIDEA => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption'),
'twoFactorOptional', 'twoFactorCaption', 'twoFactorAttribute'),
TwoFactorProviderService::TWO_FACTOR_YUBICO => array('twoFactorURL', 'twoFactorInsecure', 'twoFactorLabel',
'twoFactorOptional', 'twoFactorCaption', 'twoFactorClientId', 'twoFactorSecretKey'),
));
$row->add($twoFactorSelect, 12);
$twoFactorAttribute = new htmlResponsiveInputField(_("User name attribute"), 'twoFactorAttribute', $conf->getTwoFactorAuthenticationAttribute(), '528');
$row->add($twoFactorAttribute, 12);
$twoFactorUrl = new htmlResponsiveInputField(_("Base URL"), 'twoFactorURL', $conf->getTwoFactorAuthenticationURL(), '515');
$twoFactorUrl->setRequired(true);
$row->add($twoFactorUrl, 12);

View File

@ -572,12 +572,6 @@ if(isset($_POST['checklogin'])) {
}
else {
$_SESSION['2factorRequired'] = true;
if (($_SESSION['config']->getLoginMethod() == LAMConfig::LOGIN_SEARCH) && ($_SESSION['config']->getHttpAuthentication() == 'true')) {
$_SESSION['user2factor'] = $_SERVER['PHP_AUTH_USER'];
}
else {
$_SESSION['user2factor'] = $_POST['username'];
}
metaRefresh("./login2Factor.php");
}
die();

View File

@ -46,10 +46,7 @@ setlanguage();
$config = $_SESSION['config'];
$password = $_SESSION['ldap']->getPassword();
$user = $_SESSION['user2factor'];
if (get_preg($user, 'dn')) {
$user = extractRDNValue($user);
}
$user = $_SESSION['ldap']->getUserName();
// get serials
try {
@ -69,7 +66,6 @@ $twoFactorLabel = empty($twoFactorLabelConfig) ? _('PIN+Token') : $twoFactorLabe
if (sizeof($serials) == 0) {
if ($config->getTwoFactorAuthenticationOptional()) {
unset($_SESSION['2factorRequired']);
unset($_SESSION['user2factor']);
metaRefresh("main.php");
die();
}
@ -104,7 +100,6 @@ if (isset($_POST['submit'])) {
}
if ($twoFactorValid) {
unset($_SESSION['2factorRequired']);
unset($_SESSION['user2factor']);
metaRefresh("main.php");
die();
}

View File

@ -3,7 +3,7 @@
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2016 - 2017 Roland Gruber
Copyright (C) 2016 - 2019 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
@ -587,6 +587,17 @@ class LAMConfigTest extends PHPUnit_Framework_TestCase {
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationCaption());
}
/**
* Tests LAMConfig->getTwoFactorAuthenticationAttribute() and LAMConfig->setTwoFactorAuthenticationAttribute()
*/
public function testTwoFactorAuthenticationAttribute() {
$val = 'user';
$this->lAMConfig->setTwoFactorAuthenticationAttribute($val);
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationAttribute());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getTwoFactorAuthenticationAttribute());
}
/**
* Tests LAMConfig->getLamProMailFrom() and LAMConfig->setLamProMailFrom()
*/