mirror of
https://github.com/humhub/humhub.git
synced 2025-01-16 21:58:17 +01:00
LDAP improvements (ID attribute, PrimaryClient.php interface change)
This commit is contained in:
parent
c142a9951b
commit
7582f149d4
@ -1,6 +1,15 @@
|
||||
HumHub Change Log
|
||||
=================
|
||||
|
||||
1.2.2 (Not released yet)
|
||||
--------------------------------
|
||||
|
||||
Important note for LDAP users: There is a new setting "ID Attribute" which should be set to clearly identify users.
|
||||
|
||||
- Enh: Updated primary auth client interface for more flexibility
|
||||
- Enh: Added LDAP ID attribute to improve user mapping
|
||||
|
||||
|
||||
|
||||
1.2.2 (August 2, 2017)
|
||||
--------------------------------
|
||||
|
@ -29,6 +29,7 @@ class AuthenticationLdapSettingsForm extends \yii\base\Model
|
||||
public $userFilter;
|
||||
public $usernameAttribute;
|
||||
public $emailAttribute;
|
||||
public $idAttribute;
|
||||
public $encryptionTypes = [
|
||||
'' => 'None',
|
||||
'tls' => 'TLS (aka SSLV2)',
|
||||
@ -57,6 +58,7 @@ class AuthenticationLdapSettingsForm extends \yii\base\Model
|
||||
$this->userFilter = $settingsManager->get('auth.ldap.userFilter');
|
||||
$this->usernameAttribute = $settingsManager->get('auth.ldap.usernameAttribute');
|
||||
$this->emailAttribute = $settingsManager->get('auth.ldap.emailAttribute');
|
||||
$this->idAttribute = $settingsManager->get('auth.ldap.idAttribute');
|
||||
|
||||
if ($this->password != '')
|
||||
$this->password = '---hidden---';
|
||||
@ -68,7 +70,7 @@ class AuthenticationLdapSettingsForm extends \yii\base\Model
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['enabled', 'refreshUsers', 'usernameAttribute', 'emailAttribute', 'username', 'password', 'hostname', 'port', 'baseDn', 'loginFilter', 'userFilter'], 'string', 'max' => 255],
|
||||
[['enabled', 'refreshUsers', 'usernameAttribute', 'emailAttribute', 'username', 'password', 'hostname', 'port', 'baseDn', 'loginFilter', 'userFilter', 'idAttribute'], 'string', 'max' => 255],
|
||||
[['usernameAttribute', 'username', 'password', 'hostname', 'port', 'baseDn', 'loginFilter', 'userFilter'], 'required'],
|
||||
['encryption', 'in', 'range' => ['', 'ssl', 'tls']],
|
||||
];
|
||||
@ -92,6 +94,26 @@ class AuthenticationLdapSettingsForm extends \yii\base\Model
|
||||
'userFilter' => Yii::t('AdminModule.forms_AuthenticationLdapSettingsForm', 'User Filer'),
|
||||
'usernameAttribute' => Yii::t('AdminModule.forms_AuthenticationLdapSettingsForm', 'Username Attribute'),
|
||||
'emailAttribute' => Yii::t('AdminModule.forms_AuthenticationLdapSettingsForm', 'E-Mail Address Attribute'),
|
||||
'idAttribute' => Yii::t('AdminModule.forms_AuthenticationLdapSettingsForm', 'ID Attribute'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeHints()
|
||||
{
|
||||
return [
|
||||
'encryption' => Yii::t('AdminModule.views_setting_authentication_ldap', 'A TLS/SSL is strongly favored in production environments to prevent passwords from be transmitted in clear text.'),
|
||||
'username' => Yii::t('AdminModule.views_setting_authentication_ldap', 'The default credentials username. Some servers require that this be in DN form. This must be given in DN form if the LDAP server requires a DN to bind and binding should be possible with simple usernames.'),
|
||||
'password' => Yii::t('AdminModule.views_setting_authentication_ldap', 'The default credentials password (used only with username above).'),
|
||||
'baseDn' => Yii::t('AdminModule.views_setting_authentication_ldap', 'The default base DN used for searching for accounts.'),
|
||||
'loginFilter' => Yii::t('AdminModule.views_setting_authentication_ldap', 'Defines the filter to apply, when login is attempted. %s replaces the username in the login action. Example: "(sAMAccountName=%s)" or "(uid=%s)"'),
|
||||
'usernameAttribute' => Yii::t('AdminModule.views_setting_authentication_ldap', 'LDAP Attribute for Username. Example: "uid" or "sAMAccountName"'),
|
||||
'emailAttribute' => Yii::t('AdminModule.views_setting_authentication_ldap', 'LDAP Attribute for E-Mail Address. Default: "mail"'),
|
||||
'idAttribute' => Yii::t('AdminModule.forms_AuthenticationLdapSettingsForm', 'Not changeable LDAP attribute to unambiguously identify the user in the directory. If empty the user will be determined automatically by e-mail address or username. Examples: objectguid (ActiveDirectory) or uidNumber (OpenLDAP)'),
|
||||
'userFilter' => Yii::t('AdminModule.views_setting_authentication_ldap', 'Limit access to users meeting this criteria. Example: "(objectClass=posixAccount)" or "(&(objectClass=person)(memberOf=CN=Workers,CN=Users,DC=myDomain,DC=com))"'),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@ -117,6 +139,7 @@ class AuthenticationLdapSettingsForm extends \yii\base\Model
|
||||
$settingsManager->set('auth.ldap.userFilter', $this->userFilter);
|
||||
$settingsManager->set('auth.ldap.usernameAttribute', $this->usernameAttribute);
|
||||
$settingsManager->set('auth.ldap.emailAttribute', $this->emailAttribute);
|
||||
$settingsManager->set('auth.ldap.idAttribute', $this->idAttribute);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var $this \yii\web\View
|
||||
* @var $enabled boolean
|
||||
@ -9,7 +10,6 @@
|
||||
use humhub\models\Setting;
|
||||
use yii\helpers\Html;
|
||||
use yii\widgets\ActiveForm;
|
||||
|
||||
?>
|
||||
|
||||
<?php $this->beginContent('@admin/views/authentication/_authenticationLayout.php') ?>
|
||||
@ -22,10 +22,12 @@ use yii\widgets\ActiveForm;
|
||||
<?php if ($enabled): ?>
|
||||
<?php if ($errorMessage != ""): ?>
|
||||
<div class="alert alert-danger"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'Status: Error! (Message: {message})', ['{message}' => $errorMessage]); ?></div>
|
||||
<?php else: ?>
|
||||
<?php elseif ($userCount == 0): ?>
|
||||
<div class="alert alert-warning"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'Status: Warning! (No users found using the ldap user filter!)'); ?></div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-success"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'Status: OK! ({userCount} Users)', ['{userCount}' => $userCount]); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php $form = ActiveForm::begin(['id' => 'authentication-settings-form']); ?>
|
||||
|
||||
@ -33,37 +35,19 @@ use yii\widgets\ActiveForm;
|
||||
<hr>
|
||||
|
||||
<?= $form->field($model, 'hostname')->textInput(['readonly' => Setting::IsFixed('auth.ldap.hostname', 'user')]); ?>
|
||||
|
||||
<?= $form->field($model, 'port')->textInput(['readonly' => Setting::IsFixed('auth.ldap.port', 'user')]); ?>
|
||||
|
||||
<?= $form->field($model, 'encryption')->dropDownList($model->encryptionTypes, ['readonly' => Setting::IsFixed('auth.ldap.encryption', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'A TLS/SSL is strongly favored in production environments to prevent passwords from be transmitted in clear text.'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'username')->textInput(['readonly' => Setting::IsFixed('auth.ldap.username', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'The default credentials username. Some servers require that this be in DN form. This must be given in DN form if the LDAP server requires a DN to bind and binding should be possible with simple usernames.'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'password')->passwordInput(['readonly' => Setting::IsFixed('auth.ldap.password', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'The default credentials password (used only with username above).'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'baseDn')->textInput(['readonly' => Setting::IsFixed('auth.ldap.baseDn', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'The default base DN used for searching for accounts.'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'loginFilter')->textInput(['readonly' => Setting::IsFixed('auth.ldap.loginFilter', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'Defines the filter to apply, when login is attempted. %s replaces the username in the login action. Example: "(sAMAccountName=%s)" or "(uid=%s)"'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'userFilter')->textInput(['readonly' => Setting::IsFixed('auth.ldap.userFilter', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'Limit access to users meeting this criteria. Example: "(objectClass=posixAccount)" or "(&(objectClass=person)(memberOf=CN=Workers,CN=Users,DC=myDomain,DC=com))"'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'usernameAttribute')->textInput(['readonly' => Setting::IsFixed('auth.ldap.usernameAttribute', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'LDAP Attribute for Username. Example: "uid" or "sAMAccountName"'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'emailAttribute')->textInput(['readonly' => Setting::IsFixed('auth.ldap.emailAttribute', 'user')]); ?>
|
||||
<p class="help-block"><?= Yii::t('AdminModule.views_setting_authentication_ldap', 'LDAP Attribute for E-Mail Address. Default: "mail"'); ?></p>
|
||||
|
||||
<?= $form->field($model, 'idAttribute')->textInput(['readonly' => Setting::IsFixed('auth.ldap.idAttribute', 'user')]); ?>
|
||||
<?= $form->field($model, 'refreshUsers')->checkbox(['readonly' => Setting::IsFixed('auth.ldap.refreshUsers', 'user')]); ?>
|
||||
|
||||
<hr>
|
||||
|
||||
<?= Html::submitButton(Yii::t('AdminModule.views_setting_authentication_ldap', 'Save'), ['class' => 'btn btn-primary', 'data-ui-loader' => ""]); ?>
|
||||
|
||||
<?= \humhub\widgets\DataSaved::widget(); ?>
|
||||
|
@ -36,10 +36,7 @@ class AuthClientHelpers
|
||||
/**
|
||||
* @var interfaces\PrimaryClient $authClient
|
||||
*/
|
||||
return User::findOne([
|
||||
$authClient->getUserTableIdAttribute() => $attributes['id'],
|
||||
'auth_mode' => $authClient->getId()
|
||||
]);
|
||||
return $authClient->getUser();
|
||||
}
|
||||
|
||||
$auth = Auth::find()->where(['source' => $authClient->getId(), 'source_id' => $attributes['id']])->one();
|
||||
@ -122,7 +119,7 @@ class AuthClientHelpers
|
||||
$attributes = $authClient->getUserAttributes();
|
||||
foreach ($authClient->getSyncAttributes() as $attributeName) {
|
||||
if (isset($attributes[$attributeName])) {
|
||||
if (in_array($attributeName, ['email', 'username'])) {
|
||||
if (in_array($attributeName, ['email', 'username', 'authclient_id'])) {
|
||||
$user->setAttribute($attributeName, $attributes[$attributeName]);
|
||||
} else {
|
||||
$user->profile->setAttribute($attributeName, $attributes[$attributeName]);
|
||||
@ -165,7 +162,7 @@ class AuthClientHelpers
|
||||
$registration = new \humhub\modules\user\models\forms\Registration();
|
||||
$registration->enablePasswordForm = false;
|
||||
$registration->enableEmailField = true;
|
||||
|
||||
|
||||
if ($authClient instanceof interfaces\ApprovalBypass) {
|
||||
$registration->enableUserApproval = false;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\authclient;
|
||||
|
||||
use humhub\modules\user\models\User;
|
||||
@ -41,14 +42,6 @@ class Password extends BaseFormAuth implements interfaces\PrimaryClient
|
||||
return 'Password';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getUserTableIdAttribute()
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@ -64,4 +57,13 @@ class Password extends BaseFormAuth implements interfaces\PrimaryClient
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
$attributes = $this->getUserAttributes();
|
||||
return User::findOne(['id' => $attributes['id'], 'auth_mode' => $this->getId()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use Zend\Ldap\Node;
|
||||
use Zend\Ldap\Exception\LdapException;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\user\models\ProfileField;
|
||||
use humhub\modules\user\libs\LdapHelper;
|
||||
|
||||
/**
|
||||
* LDAP Authentication
|
||||
@ -30,7 +31,7 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
private $_ldap = null;
|
||||
|
||||
/**
|
||||
* ID attribute to uniquely identify user
|
||||
* ID attribute to uniquely identify user.
|
||||
* If set to null, automatically a value email or objectguid will be used if available.
|
||||
*
|
||||
* @var string attribute name to identify node
|
||||
@ -38,15 +39,84 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
public $idAttribute = null;
|
||||
|
||||
/**
|
||||
* @var string attribute name to user record
|
||||
* @var string the email attribute
|
||||
*/
|
||||
public $userTableIdAttribute = 'guid';
|
||||
public $emailAttribute = null;
|
||||
|
||||
/**
|
||||
* @var string the ldap username attribute
|
||||
*/
|
||||
public $usernameAttribute = null;
|
||||
|
||||
/**
|
||||
* @var string the ldap base dn
|
||||
*/
|
||||
public $baseDn = null;
|
||||
|
||||
/**
|
||||
* @var string the ldap query to find humhub users
|
||||
*/
|
||||
public $userFilter = null;
|
||||
|
||||
/**
|
||||
* Automatically refresh user profiles on cron run
|
||||
*
|
||||
* @var boolean|null
|
||||
*/
|
||||
public $autoRefreshUsers = null;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $byPassApproval = true;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
$settings = Yii::$app->getModule('user')->settings;
|
||||
|
||||
if ($this->idAttribute === null) {
|
||||
$idAttribute = $settings->get('auth.ldap.idAttribute');
|
||||
if (!empty($idAttribute)) {
|
||||
$this->idAttribute = strtolower($idAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->usernameAttribute === null) {
|
||||
$usernameAttribute = $settings->get('auth.ldap.usernameAttribute');
|
||||
if (!empty($usernameAttribute)) {
|
||||
$this->usernameAttribute = strtolower($usernameAttribute);
|
||||
} else {
|
||||
$this->usernameAttribute = 'samaccountname';
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->emailAttribute === null) {
|
||||
$emailAttribute = $settings->get('auth.ldap.emailAttribute');
|
||||
if (!empty($emailAttribute)) {
|
||||
$this->emailAttribute = strtolower($emailAttribute);
|
||||
} else {
|
||||
$this->emailAttribute = 'mail';
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->userFilter === null) {
|
||||
$this->userFilter = Yii::$app->getModule('user')->settings->get('auth.ldap.userFilter');
|
||||
}
|
||||
|
||||
if ($this->baseDn === null) {
|
||||
$this->baseDn = Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn');
|
||||
}
|
||||
|
||||
if ($this->autoRefreshUsers === null) {
|
||||
$this->autoRefreshUsers = (boolean) Yii::$app->getModule('user')->settings->get('auth.ldap.refreshUsers');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@ -80,11 +150,59 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
}
|
||||
|
||||
/**
|
||||
* Find user based on ldap attributes
|
||||
*
|
||||
* @inheritdoc
|
||||
* @see interfaces\PrimaryClient
|
||||
* @return User the user
|
||||
*/
|
||||
public function getUserTableIdAttribute()
|
||||
public function getUser()
|
||||
{
|
||||
return $this->userTableIdAttribute;
|
||||
$attributes = $this->getUserAttributes();
|
||||
|
||||
// Try to load user by ldap id attribute
|
||||
if ($this->idAttribute !== null && isset($attributes['authclient_id'])) {
|
||||
$user = User::findOne(['authclient_id' => $attributes['authclient_id'], 'auth_mode' => $this->getId()]);
|
||||
if ($user !== null) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getUserAuto();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find the user if authclient_id mapping is not set yet (legency)
|
||||
* or idAttribute is not specified.
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
protected function getUserAuto()
|
||||
{
|
||||
$attributes = $this->getUserAttributes();
|
||||
|
||||
// Try to find user user if authclient_id is null based on ldap fields objectguid and e-mail
|
||||
$query = User::find();
|
||||
$query->where(['auth_mode' => $this->getId()]);
|
||||
|
||||
if ($this->idAttribute !== null) {
|
||||
$query->andWhere(['IS', 'authclient_id', new \yii\db\Expression('NULL')]);
|
||||
}
|
||||
|
||||
$conditions = ['OR'];
|
||||
if (isset($attributes['email']) && !empty($attributes['email'])) {
|
||||
$conditions[] = ['email' => $attributes['email']];
|
||||
}
|
||||
if (isset($attributes['objectguid']) && !empty($attributes['objectguid'])) {
|
||||
$conditions[] = ['guid' => $attributes['objectguid']];
|
||||
}
|
||||
if (isset($attributes['uid']) && !empty($attributes['uid'])) {
|
||||
$conditions[] = ['username' => $attributes['uid']];
|
||||
}
|
||||
if ($conditions)
|
||||
$query->andWhere($conditions);
|
||||
|
||||
return $query->one();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,7 +210,6 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
|
||||
$node = $this->getUserNode();
|
||||
if ($node !== null) {
|
||||
$this->setUserAttributes($node->getAttributes());
|
||||
@ -108,20 +225,8 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
protected function defaultNormalizeUserAttributeMap()
|
||||
{
|
||||
$map = [];
|
||||
|
||||
// Username field
|
||||
$usernameAttribute = Yii::$app->getModule('user')->settings->get('auth.ldap.usernameAttribute');
|
||||
if ($usernameAttribute == '') {
|
||||
$usernameAttribute = 'sAMAccountName';
|
||||
}
|
||||
$map['username'] = strtolower($usernameAttribute);
|
||||
|
||||
// E-Mail field
|
||||
$emailAttribute = Yii::$app->getModule('user')->settings->get('auth.ldap.emailAttribute');
|
||||
if ($emailAttribute == '') {
|
||||
$emailAttribute = 'mail';
|
||||
}
|
||||
$map['email'] = strtolower($emailAttribute);
|
||||
$map['username'] = $this->usernameAttribute;
|
||||
$map['email'] = $this->emailAttribute;
|
||||
|
||||
// Profile Field Mapping
|
||||
foreach (ProfileField::find()->andWhere(['!=', 'ldap_attribute', ''])->all() as $profileField) {
|
||||
@ -164,6 +269,13 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->idAttribute !== null && isset($normalized[$this->idAttribute])) {
|
||||
$normalized['authclient_id'] = $normalized[$this->idAttribute];
|
||||
}
|
||||
|
||||
$normalized['id'] = 'unused';
|
||||
|
||||
return parent::normalizeUserAttributes($normalized);
|
||||
}
|
||||
|
||||
@ -174,27 +286,11 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
{
|
||||
$attributes = parent::getUserAttributes();
|
||||
|
||||
// Try to automatically set id and usertable id attribute by available attributes
|
||||
if ($this->getIdAttribute() === null || $this->getUserTableIdAttribute() === null) {
|
||||
if (isset($attributes['objectguid'])) {
|
||||
$this->idAttribute = 'objectguid';
|
||||
$this->userTableIdAttribute = 'guid';
|
||||
} elseif (isset($attributes['mail'])) {
|
||||
$this->idAttribute = 'mail';
|
||||
$this->userTableIdAttribute = 'email';
|
||||
} else {
|
||||
throw new \yii\base\Exception("Could not automatically determine unique user id from ldap node!");
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure id attributes sits on id attribute key
|
||||
if (isset($attributes[$this->getIdAttribute()])) {
|
||||
$attributes['id'] = $attributes[$this->getIdAttribute()];
|
||||
}
|
||||
|
||||
// Map usertable id attribute against ldap id attribute
|
||||
$attributes[$this->getUserTableIdAttribute()] = $attributes[$this->getIdAttribute()];
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
@ -247,20 +343,7 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
public function getLdap()
|
||||
{
|
||||
if ($this->_ldap === null) {
|
||||
$options = array(
|
||||
'host' => Yii::$app->getModule('user')->settings->get('auth.ldap.hostname'),
|
||||
'port' => Yii::$app->getModule('user')->settings->get('auth.ldap.port'),
|
||||
'username' => Yii::$app->getModule('user')->settings->get('auth.ldap.username'),
|
||||
'password' => Yii::$app->getModule('user')->settings->get('auth.ldap.password'),
|
||||
'useStartTls' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'tls'),
|
||||
'useSsl' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'ssl'),
|
||||
'bindRequiresDn' => true,
|
||||
'baseDn' => Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn'),
|
||||
'accountFilterFormat' => Yii::$app->getModule('user')->settings->get('auth.ldap.loginFilter'),
|
||||
);
|
||||
|
||||
$this->_ldap = new \Zend\Ldap\Ldap($options);
|
||||
$this->_ldap->bind();
|
||||
$this->_ldap = LdapHelper::getLdapConnection();
|
||||
}
|
||||
|
||||
return $this->_ldap;
|
||||
@ -281,7 +364,7 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
*/
|
||||
public function getSyncAttributes()
|
||||
{
|
||||
$attributes = ['username', 'email'];
|
||||
$attributes = ['username', 'email', 'authclient_id'];
|
||||
|
||||
foreach (ProfileField::find()->andWhere(['!=', 'ldap_attribute', ''])->all() as $profileField) {
|
||||
$attributes[] = $profileField->internal_name;
|
||||
@ -298,16 +381,14 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
*/
|
||||
public function syncUsers()
|
||||
{
|
||||
if (!Yii::$app->getModule('user')->settings->get('auth.ldap.enabled') || !Yii::$app->getModule('user')->settings->get('auth.ldap.refreshUsers')) {
|
||||
if (!LdapHelper::isLdapEnabled() || !$this->autoRefreshUsers) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userFilter = Yii::$app->getModule('user')->settings->get('auth.ldap.userFilter');
|
||||
$baseDn = Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn');
|
||||
try {
|
||||
$ldap = $this->getLdap();
|
||||
|
||||
$userCollection = $ldap->search($userFilter, $baseDn, Ldap::SEARCH_SCOPE_SUB);
|
||||
$userCollection = $ldap->search($this->userFilter, $this->baseDn, Ldap::SEARCH_SCOPE_SUB);
|
||||
|
||||
$authClient = null;
|
||||
$ids = [];
|
||||
@ -326,30 +407,27 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
AuthClientHelpers::updateUser($authClient, $user);
|
||||
}
|
||||
|
||||
$ids[] = $attributes['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Since userTableAttribute can be automatically set on user attributes
|
||||
* try to take it from initialized authclient instance.
|
||||
*/
|
||||
$userTableIdAttribute = $this->getUserTableIdAttribute();
|
||||
if ($authClient !== null) {
|
||||
$userTableIdAttribute = $authClient->getUserTableIdAttribute();
|
||||
if (isset($attributes['authclient_id'])) {
|
||||
$ids[] = $attributes['authclient_id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach (AuthClientHelpers::getUsersByAuthClient($this)->each() as $user) {
|
||||
$foundInLdap = in_array($user->getAttribute($userTableIdAttribute), $ids);
|
||||
// Enable disabled users that have been found in ldap
|
||||
if ($foundInLdap && $user->status === User::STATUS_DISABLED) {
|
||||
$user->status = User::STATUS_ENABLED;
|
||||
$user->save();
|
||||
Yii::info('Enabled user' . $user->username . ' (' . $user->id . ') - found in LDAP!');
|
||||
// Disable users that were not found in ldap
|
||||
} elseif (!$foundInLdap && $user->status !== User::STATUS_DISABLED) {
|
||||
$user->status = User::STATUS_DISABLED;
|
||||
$user->save();
|
||||
Yii::warning('Disabled user' . $user->username . ' (' . $user->id . ') - not found in LDAP!');
|
||||
// Disable or Reenable Users based on collected $ids Arrays
|
||||
// This is only possible if a unique id attribute is specified.
|
||||
if ($this->idAttribute !== null) {
|
||||
foreach (AuthClientHelpers::getUsersByAuthClient($this)->each() as $user) {
|
||||
$foundInLdap = in_array($user->authclient_id, $ids);
|
||||
if ($foundInLdap && $user->status === User::STATUS_DISABLED) {
|
||||
// Enable disabled users that have been found in ldap
|
||||
$user->status = User::STATUS_ENABLED;
|
||||
$user->save();
|
||||
Yii::info('Enabled user' . $user->username . ' (' . $user->id . ') - found in LDAP!');
|
||||
} elseif (!$foundInLdap && $user->status !== User::STATUS_DISABLED) {
|
||||
// Disable users that were not found in ldap
|
||||
$user->status = User::STATUS_DISABLED;
|
||||
$user->save();
|
||||
Yii::warning('Disabled user' . $user->username . ' (' . $user->id . ') - not found in LDAP!');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Zend\Ldap\Exception\LdapException $ex) {
|
||||
@ -361,18 +439,13 @@ class ZendLdapClient extends BaseFormAuth implements interfaces\AutoSyncUsers, i
|
||||
|
||||
/**
|
||||
* Checks if LDAP is supported
|
||||
*
|
||||
* @deprecated since version 1.2.3
|
||||
* @return boolean is LDAP supported (drivers, modules)
|
||||
*/
|
||||
public static function isLdapAvailable()
|
||||
{
|
||||
if (!class_exists('Zend\Ldap\Ldap')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!function_exists('ldap_bind')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return LdapHelper::isLdapAvailable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -20,10 +20,10 @@ interface PrimaryClient
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the user model attribute name which should be mapped against
|
||||
* the id attribute in the authClient user attributes.
|
||||
* Returns the user model of this auth client
|
||||
*
|
||||
* @return string the user model id attribute e.g. id, guid or email
|
||||
* @since 1.2.2
|
||||
* @return \humhub\modules\user\models\User
|
||||
*/
|
||||
public function getUserTableIdAttribute();
|
||||
public function getUser();
|
||||
}
|
||||
|
74
protected/humhub/modules/user/libs/LdapHelper.php
Normal file
74
protected/humhub/modules/user/libs/LdapHelper.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\modules\user\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidParamException;
|
||||
use Zend\Ldap\Ldap;
|
||||
use Zend\Ldap\Exception\LdapException;
|
||||
use humhub\modules\user\authclient\ZendLdapClient;
|
||||
|
||||
/**
|
||||
* This class contains a lot of html helpers for the views
|
||||
*
|
||||
* @since 0.5
|
||||
*/
|
||||
class LdapHelper
|
||||
{
|
||||
|
||||
public static function getLdapConnection()
|
||||
{
|
||||
$options = array(
|
||||
'host' => Yii::$app->getModule('user')->settings->get('auth.ldap.hostname'),
|
||||
'port' => Yii::$app->getModule('user')->settings->get('auth.ldap.port'),
|
||||
'username' => Yii::$app->getModule('user')->settings->get('auth.ldap.username'),
|
||||
'password' => Yii::$app->getModule('user')->settings->get('auth.ldap.password'),
|
||||
'useStartTls' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'tls'),
|
||||
'useSsl' => (Yii::$app->getModule('user')->settings->get('auth.ldap.encryption') == 'ssl'),
|
||||
'bindRequiresDn' => true,
|
||||
'baseDn' => Yii::$app->getModule('user')->settings->get('auth.ldap.baseDn'),
|
||||
'accountFilterFormat' => Yii::$app->getModule('user')->settings->get('auth.ldap.loginFilter'),
|
||||
);
|
||||
|
||||
$ldap = new \Zend\Ldap\Ldap($options);
|
||||
$ldap->bind();
|
||||
|
||||
return $ldap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if LDAP support is enabled
|
||||
*
|
||||
* @return boolean is LDAP support is enabled
|
||||
*/
|
||||
public static function isLdapEnabled()
|
||||
{
|
||||
return (boolean) Yii::$app->getModule('user')->settings->get('auth.ldap.enabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if LDAP is supported
|
||||
*/
|
||||
public static function isLdapAvailable()
|
||||
{
|
||||
if (!class_exists('Zend\Ldap\Ldap')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!function_exists('ldap_bind')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
class m170805_211208_authclient_id extends Migration
|
||||
{
|
||||
|
||||
public function safeUp()
|
||||
{
|
||||
$this->addColumn('user', 'authclient_id', $this->string(60)->null());
|
||||
$this->createIndex('unique_authclient_id', 'user', ['authclient_id'], true);
|
||||
}
|
||||
|
||||
public function safeDown()
|
||||
{
|
||||
echo "m170805_211208_authclient_id cannot be reverted.\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
// Use up()/down() to run migration code without a transaction.
|
||||
public function up()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
echo "m170805_211208_authclient_id cannot be reverted.\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
@ -33,6 +33,7 @@ use humhub\modules\content\models\Content;
|
||||
* @property string $updated_at
|
||||
* @property integer $updated_by
|
||||
* @property string $last_login
|
||||
* @property string $authclient_id
|
||||
* @property integer $visibility
|
||||
* @property integer $contentcontainer_id
|
||||
* @property Profile $profile
|
||||
|
Loading…
x
Reference in New Issue
Block a user