First a disclaimer beforehand: the posted code snippets are all basic examples. You'll need to handle trivial Exceptions and further logic by yourself.
I will post a fast hack to achieve a simple AD authentication with the Yii2 advance template, which will take a username/password and authenticate this combination against a MS Active Directory domain controller. In addition, it checks a given group membership from the user, for which reason only users with this group can log in.
We assume that:
- The user (particular the username) have to exist in the current
user table (check out the Authorization Guide to build the
rbac structure). We assume further that the username from our database is the same username you want to authenticate against the AD.
- You have set up correctly an Adldap2 wrapper for Yii2 (like alexeevdv/yii2-adldap) or load Adladp2 as a vendor module. Benefit from the wrapper: You can configure the adldap2 class in your components section of the application configuration and then you can use the wrapper as a Yii2 component.
- Your PHP-Environment use the LDAP-Extension (e.g. run something like apt-get install php5-ldap on debian distributions).
- You have some admin credentials to connect to the domain controller with the permission to query the AD in the way you want.
So, lets start with the basic set-up.
Set up the wrapper config (e.g. config/main-local.php).
'components' => [
'ldap' => [
'class' => 'alexeevdv\adldap\Adldap',
'options' => [
'account_suffix' => '@stackoverflow.com',
'domain_controllers' => ['dc1.stackoverflow.com', 'dc2.stackoverflow.com'],
'base_dn' => 'dc=stackoverflow,dc=com',
'admin_username' => 'someusername',
'admin_password' => 'somepassword',
'use_ssl' => true,
'port' => '636'
],
],
],
I want to switch easily between ldap and local authentication. Configure some local params to have globally accessible application parameters (e.g. config/params-local.php).
return [
'adminEmail' => '[email protected]',
'authOverLdap' => true,
'ldapGroup' => 'someldapgroup',
];
Edit your LoginForm.php, especially the validatePassword function (e.g. common/models/LoginForm.php).
/**
* Validates the password.
* This method serves as the inline validation for password.
* If the authOverLdap attribute is set in the params config,
* user and password will be authenticated over ldap
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
// to switch between the auth-methods
$authOverLdap = \Yii::$app->params['authOverLdap'];
if ($authOverLdap) {
if (!$user || !$user->validateCredentialsOverLdap($user->username, $this->password)) {
$this->addError($attribute, 'Some error text.');
}
} else {
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Some error text.');
}
}
}
}
Add the validateCredentialsOverLdap function in the user model which handles the LDAP auth (e.g. /common/models/User.php).
/**
* Validates a user/password combination over ldap
*
* @param string $username username to validate over ldap
* @param string $password password to validate over ldap
* @return boolean if the provided credentials are correct and the user is a member of **ldapGroup**
*/
public function validateCredentialsOverLdap($username, $password)
{
$authSuccess = false;
// checking the supplied credentials against the ldap (e.g. Active Directory)
// first step: the user must have a valid account
// second step: the user must be in a special group
$authOk = \Yii::$app->ldap->authenticate($username, $password);
if ($authOk) {
$adUser = \Yii::$app->ldap->users()->find($username);
// the user must be in special group (set in Yii params)
if($adUser->inGroup(\Yii::$app->params['ldapGroup'])) {
$authSuccess = true;
}
}
return $authSuccess;
}
Disclaimer:
- Don't copy&paste these snippets! You have to know what are you doing!
- This shall show you an example and give you a hint to achieve AD authentication with the wrapper and the Yii2 Framework.
- I run this code in a walled garden intranet!
- Use ever, ever the secure layers like SSL to communicate over LDAP! You dont know who is sniffing the traffic in your problably safe network. You dealing with User credentials. This can be a massive fuck up, especially in Single Sign On Environments! Don't be silly.