Closed rccoder closed 9 years ago
Hi,
Happy to see that this plugin is useful to others. I assume that you add the parameter auth_cas_autocreate_permissions in config array of your config.php :
... // Use the following config variable to set modified optional settings copied from config-defaults.php 'config'=>array( 'auth_cas_autocreate_permissions' => array( 'surveys' => array('create'=>true) ),
// debug: Set this to 1 if you are looking for errors. If you still get no errors after enabling this // then please check your error-logs - either in your hosting provider admin panel or in some /logs directory ...
Where do you get the information about the user ? LDAP or CAS attributes ? If LDAP, did you define a filter to restrict the type of user allowed to create an account automatically ?
It would be helpful to have more information about your configuration to help find the origin of the problem.
yep, the config of my file is
// Use the following config variable to set modified optional settings copied from config-defaults.php
'config'=>array(
'auth_cas_autocreate_permissions' => array (
'surveys' => array('create' => true)
),
// debug: Set this to 1 if you are looking for errors. If you still get no errors after enabling this
// then please check your error-logs - either in your hosting provider admin panel or in some /logs directory
// on your webspace.
// LimeSurvey developers: Set this to 2 to additionally display STRICT PHP error messages and get full access to standard templates
'debug'=>0,
'debugsql'=>0 // Set this to 1 to enanble sql logging, only active when debug = 2
),
and for the plugin, AuthCAS.php is is:
<?php
class AuthCAS extends AuthPluginBase
{
protected $storage = 'DbStorage';
static protected $description = 'Core: CAS authentication';
static protected $name = 'CAS';
protected $settings = array(
'casAuthServer' => array(
'type' => 'string',
'label' => 'The servername of the CAS Server without protocol',
'default' => 'localhost',
),
'casAuthPort' => array(
'type' => 'int',
'label' => 'CAS Server listening Port',
'default' => 8443,
),
'casAuthUri' => array(
'type' => 'string',
'label' => 'Relative uri from CAS Server to cas workingdirectory',
'default' => '/cas',
),
'autoCreate' => array(
'type' => 'select',
'label' => 'Enable automated creation of user from LDAP ?',
'options' => array("0" => "No, don't create user automatically", "1" => "User creation on the first connection", "2" => "User creation from CAS attributes"),
'default' => '0',
'submitonchange' => true
),
'casLoginAttr' => array(
'type' => 'string',
'label' => 'CAS attribute for login',
'default' => 'uid'
),
'casFullnameAttr' => array(
'type' => 'string',
'label' => 'CAS attribute for fullname',
'default' => 'displayName'
),
'server' => array(
'type' => 'string',
'label' => 'Ldap server e.g. ldap://ldap.mydomain.com or ldaps://ldap.mydomain.com'
),
'ldapport' => array(
'type' => 'string',
'label' => 'Port number (default when omitted is 389)'
),
'ldapversion' => array(
'type' => 'select',
'label' => 'LDAP version',
'options' => array('2' => 'LDAPv2', '3' => 'LDAPv3'),
'default' => '2',
'submitonchange' => true
),
'ldapoptreferrals' => array(
'type' => 'boolean',
'label' => 'Select true if referrals must be followed (use false for ActiveDirectory)',
'default' => '0'
),
'ldaptls' => array(
'type' => 'boolean',
'label' => 'Check to enable Start-TLS encryption When using LDAPv3',
'default' => '0'
),
'searchuserattribute' => array(
'type' => 'string',
'label' => 'Attribute to compare to the given login can be uid, cn, mail, ...'
),
'usersearchbase' => array(
'type' => 'string',
'label' => 'Base DN for the user search operation'
),
'extrauserfilter' => array(
'type' => 'string',
'label' => 'Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don\'t forget the outmost enclosing parentheses'
),
'binddn' => array(
'type' => 'string',
'label' => 'Optional DN of the LDAP account used to search for the end-user\'s DN. An anonymous bind is performed if empty.'
),
'bindpwd' => array(
'type' => 'string',
'label' => 'Password of the LDAP account used to search for the end-user\'s DN if previoulsy set.'
)
);
public function __construct(PluginManager $manager, $id)
{
parent::__construct($manager, $id);
/**
* Here you should handle subscribing to the events your plugin will handle
*/
$this->subscribe('beforeLogin');
$this->subscribe('newUserSession');
$this->subscribe('beforeLogout');
}
/**
* Modified getPluginSettings since we have a select box that autosubmits
* and we only want to show the relevant options.
*
* @param boolean $getValues
* @return array
*/
public function getPluginSettings($getValues = true)
{
$aPluginSettings = parent::getPluginSettings($getValues);
if ($getValues)
{
$ldapver = $aPluginSettings['ldapversion']['current'];
$autoCreate = $aPluginSettings['autoCreate']['current'];
// If it is a post request, it could be an autosubmit so read posted
// value over the saved value
if (App()->request->isPostRequest)
{
$ldapver = App()->request->getPost('ldapversion', $ldapver);
$aPluginSettings['ldapversion']['current'] = $ldapver;
$autoCreate = App()->request->getPost('autoCreate', $autoCreate);
$aPluginSettings['autoCreate']['current'] = $autoCreate;
}
if ($autoCreate != 1)
{
// Don't create user. Hide unneeded ldap settings
unset($aPluginSettings['server']);
unset($aPluginSettings['ldapport']);
unset($aPluginSettings['ldapversion']);
unset($aPluginSettings['ldapoptreferrals']);
unset($aPluginSettings['ldaptls']);
unset($aPluginSettings['searchuserattribute']);
unset($aPluginSettings['usersearchbase']);
unset($aPluginSettings['extrauserfilter']);
unset($aPluginSettings['binddn']);
unset($aPluginSettings['bindpwd']);
} else
{
if ($ldapver == '2')
{
unset($aPluginSettings['ldaptls']);
}
}
//不是2的情况下销毁
if ($autoCreate != 2)
{
unset($aPluginSettings['casFullnameAttr']);
unset($aPluginSettings['casLoginAttr']);
unset($aPluginSettings['casMailAttr']);
}
}
return $aPluginSettings;
}
public function beforeLogin()
{
// configure phpCAS
$cas_host = $this->get('casAuthServer');
$cas_context = $this->get('casAuthUri');
$cas_port = (int) $this->get('casAuthPort');
// import phpCAS lib
$basedir=dirname(__FILE__);
Yii::setPathOfAlias('myplugin', $basedir);
Yii::import('myplugin.third_party.CAS.*');
require_once('third_party/CAS/CAS.php');
// Initialize phpCAS
phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context, false);
// disable SSL validation of the CAS server
phpCAS::setNoCasServerValidation();
//force CAS authentication
phpCAS::forceAuthentication();
$this->setUsername(phpCAS::getUser());
$oUser = $this->api->getUserByName($this->getUserName());
if ($oUser || $this->get('autoCreate') > 0)
{
// User authenticated and found. Cas become the authentication system
$this->getEvent()->set('default', get_class($this));
$this->setAuthPlugin(); // This plugin handles authentication, halt further execution of auth plugins
} elseif ($this->get('is_default', null, null))
{
// Fall back to another authentication mecanism
throw new CHttpException(401, 'Wrong credentials for LimeSurvey administration.');
}
}
public function newUserSession()
{
// Do nothing if this user is not AuthCAS type
$identity = $this->getEvent()->get('identity');
if ($identity->plugin != 'AuthCAS')
{
return;
}
$sUser = $this->getUserName();
$oUser = $this->api->getUserByName($sUser);
if (is_null($oUser))
{
//LD
if ((int) $this->get('autoCreate') === 1)
{
// auto-create
// Get configuration settings:
$ldapserver = $this->get('server');
$ldapport = $this->get('ldapport');
$ldapver = $this->get('ldapversion');
$ldaptls = $this->get('ldaptls');
$ldapoptreferrals = $this->get('ldapoptreferrals');
$searchuserattribute = $this->get('searchuserattribute');
$extrauserfilter = $this->get('extrauserfilter');
$usersearchbase = $this->get('usersearchbase');
$binddn = $this->get('binddn');
$bindpwd = $this->get('bindpwd');
$username = $sUser;
if (empty($ldapport))
{
$ldapport = 389;
}
// Try to connect
$ldapconn = ldap_connect($ldapserver, (int) $ldapport);
if (false == $ldapconn)
{
$this->setAuthFailure(1, gT('Could not connect to LDAP server.'));
return;
}
// using LDAP version
if ($ldapver === null)
{
// If the version hasn't been set, default = 2
$ldapver = 2;
}
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, $ldapver);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, $ldapoptreferrals);
if (!empty($ldaptls) && $ldaptls == '1' && $ldapver == 3 && preg_match("/^ldaps:\/\//", $ldapserver) == 0)
{
// starting TLS secure layer
if (!ldap_start_tls($ldapconn))
{
$this->setAuthFailure(100, ldap_error($ldapconn));
ldap_close($ldapconn); // all done? close connection
return;
}
}
// We first do a LDAP search from the username given
// to find the userDN and then we procced to the bind operation
if (empty($binddn))
{
// There is no account defined to do the LDAP search,
// let's use anonymous bind instead
$ldapbindsearch = @ldap_bind($ldapconn);
} else
{
// An account is defined to do the LDAP search, let's use it
$ldapbindsearch = @ldap_bind($ldapconn, $binddn, $bindpwd);
}
if (!$ldapbindsearch)
{
$this->setAuthFailure(100, ldap_error($ldapconn));
ldap_close($ldapconn); // all done? close connection
return;
}
// Now prepare the search filter
if ($extrauserfilter != "")
{
$usersearchfilter = "(&($searchuserattribute=$username)$extrauserfilter)";
} else
{
$usersearchfilter = "($searchuserattribute=$username)";
}
// Search for the user
$dnsearchres = ldap_search($ldapconn, $usersearchbase, $usersearchfilter, array($searchuserattribute, "displayname", "mail"));
$rescount = ldap_count_entries($ldapconn, $dnsearchres);
if ($rescount == 1)
{
$userentry = ldap_get_entries($ldapconn, $dnsearchres);
$userdn = $userentry[0]["dn"];
$oUser = new User;
$oUser->users_name = $username;
$oUser->password = hash('sha256', createPassword());
$oUser->full_name = $userentry[0]["displayname"][0];
$oUser->parent_id = 1;
$oUser->email = $userentry[0]["mail"][0];
if ($oUser->save())
{
$permission = new Permission;
$permission->setPermissions($oUser->uid, 0, 'global', $this->api->getConfigKey('auth_cas_autocreate_permissions'), true);
// read again user from newly created entry
$this->setAuthSuccess($oUser);
return;
} else
{
$this->setAuthFailure(self::ERROR_USERNAME_INVALID);
throw new CHttpException(401, 'User not saved : ' . $userentry[0]["mail"][0] . " / " . $userentry[0]["displayName"]);
return;
}
} else
{
// if no entry or more than one entry returned
// then deny authentication
$this->setAuthFailure(100, ldap_error($ldapconn));
ldap_close($ldapconn); // all done? close connection
throw new CHttpException(401, 'No authorized user found for login "' . $username . '"');
return;
}
}
//PHPCAS auto
else if((int) $this->get('autoCreate') === 2)
{
try {
// import phpCAS lib
$basedir=dirname(__FILE__);
Yii::setPathOfAlias('myplugin', $basedir);
Yii::import('myplugin.third_party.CAS.*');
require_once('CAS.php');
$cas_host = $this->get('casAuthServer');
$cas_context = $this->get('casAuthUri');
$cas_port = (int) $this->get('casAuthPort');
// Initialize phpCAS
//phpCAS::client($cas_version, $cas_host, $cas_port, $cas_context, false);
// disable SSL validation of the CAS server
//phpCAS::setNoCasServerValidation();
$cas_fullname = phpCAS::getAttribute($this->get('casFullnameAttr'));
$cas_login = phpCAS::getAttribute($this->get('casLoginAttr'));
}
catch (Exception $e)
{
$this->setAuthFailure(self::ERROR_USERNAME_INVALID);
throw new CHttpException(401, 'Cas attributes not found for "' . $username . '"');
return;
}
$oUser = new User;
$oUser->users_name = phpCAS::getUser();
$oUser->password = hash('sha256', createPassword());
$oUser->full_name = $cas_fullname;
$oUser->parent_id = 1;
$oUser->email = 'example'.$cas_fullname.'@example.com';
if ($oUser->save())
{
if ($this->api->getConfigKey('auth_cas_autocreate_permissions'))
{
$permission = new Permission;
$permission->setPermissions($oUser->uid, 0, 'global', $this->api->getConfigKey('auth_cas_autocreate_permissions'), true);
}
$this->setAuthSuccess($oUser);
return;
} else
{
$this->setAuthFailure(self::ERROR_USERNAME_INVALID);
throw new CHttpException(401, 'User not saved : ' . $sUser .' / ' . $cas_fullname);
return;
}
}
} else
{
$this->setAuthSuccess($oUser);
return;
}
}
public function beforeLogout()
{
// configure phpCAS
$cas_host = $this->get('casAuthServer');
$cas_context = $this->get('casAuthUri');
$cas_port = (int) $this->get('casAuthPort');
// import phpCAS lib
$basedir=dirname(__FILE__);
Yii::setPathOfAlias('myplugin', $basedir);
Yii::import('myplugin.third_party.CAS.*');
require_once('third_party/CAS/CAS.php');
// Initialize phpCAS
phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context, false);
// disable SSL validation of the CAS server
phpCAS::setNoCasServerValidation();
// logout from CAS
phpCAS::logout();
}
}
because my cas server can't give me the email ,so I drop the email
And I get information from CAS attributes
the information is :
user:1234567
*******************
attributes:
array(5) {
["containerId"]=>
string(3) "bks"
["binduserlist"]=>
string(0) ""
["cn"]=>
string(9) "张三"
["eduPersonOrgDN"]=>
string(27) "计算机科学与工程系"
["uid"]=>
string(10) "1234567"
}
I just made a commit today that you didn't apply on your file. Try to replace these lines (3 modifications) :
Yii::import('myplugin.third_party.CAS.*');
require_once('CAS.php');
by
Yii::import('myplugin.third_party.CAS.CAS',true);
About the email, I assume that this shouldn't be a problem but I can't test it here. You may have problem depending on the user's cn. You may try to use the uid instead :
$oUser->email = 'example'.$cas_login.'@example.com';
I used you new plugin but there is a new Error.
Error 401
User not saved...
How to solve it? May be it caused by System Permissions? My server is ubuntu server
As you can see in the code, this error is generated by the plugin when the user can't be saved
throw new CHttpException(401, 'User not saved : ' . $sUser .' / ' . $cas_fullname);
The truly odd thing in your error message is that you don't get : and / in it. Even if your id and username are empty you should have these symbols. Could you provide the diff between your file and the last version of this repo to see why this happen ?
Sorroy, I am not provide all of the message
The error is :
Error 401
User not saved : twtest / twtest / 团委测试
The above error occurred when the Web server was processing your request.
If you think this is a server error, please contact the webmaster.
Thank you.
2015-08-27 18:24:55
What I used is you new plugin
As you said, The user can't be saved
Oh, Thanks
The bug caused By email. I have solved it! Thank you very much
Hi, I'm very glad to visit this repo.
I download the plugin and installed as README.md.
But some question hit me. Now, If I was create a user which ID is same as CAS ID in front of active this plugin, I can login and logout. But if I was not create user previous, I can't login and there is not create a user auto, the http status is 500.
Could you help me? Thanks