yii2ldapadldap

Yii: How to validatePassword with Edvlerblog\Adldap2 using userprincipalname instead of samaccountname


Question

Currently looking for how other people handled the validate password function when they need to authenticate with the userprincipalname instead of the Edvlerblog\Adldap2 validatePassword function which uses samaccountname.

Please provide feedback in the comments if you are struggling with anything specific so we can update the documentation.

Current Implementation

For app/common/model/LoginForm

getUser

The Edvlerblog\Adldap2 getUser() function works, and even caches the queryLdapUserObject, allowing you to fetch any of the AD attributes.

protected function getUser()
{
    if ($this->_user === null) {
        $this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
    }

    return $this->_user;
}

validatePassword()

Currently, the following validatePassword function does not work for me because in my instance AD must authenticate against the userprincipalname instead of the samaccount name.

public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();
        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError($attribute, 'Incorrect username or password.');
        }
    }
}

Solution

  • A solution

    Here is one workaround thanks to the Edvlerblog\Adldap2 who recently released 3.0.5 addressing a couple issues and providing some examples in his readme docs.

    Please note the addition of findByAttribute(), allowing the following:

     $this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
    

    validatePassword() w/ userprincipalname

    Update your login model: common\models\LoginForm.php

    public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            $user = $this->getUser();
            if (!$user) {
                $this->addError('username', 'Incorrect username.');
            } else {
                // Note: queryLdapUserObject is a cached object, 
                // so the ldap fetch does not get called :-).
                $userprincipalname = $this->_user->queryLdapUserObject()->getAttribute('userprincipalname');
                $auth = Yii::$app->ad->auth()->attempt($userprincipalname[0], $this->password);
                if (!$auth) {
                    $this->addError('password', 'Incorrect password.');
                }
            }
        }
    }
    

    getUser() w/userprincipalname

        /**
         * Finds user by [[username]]
         *
         * @return User|null
         */
        protected function getUser()
        {
            if ($this->_user === null) {
                $this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
            }
    
            return $this->_user;
        }
    

    Yii2 ldap Component Configuration

    Reference: https://github.com/Adldap2/Adldap2/blob/master/docs/configuration.md

    Config in your frontend\config\main:

    'components' => [
            'log' => [... ],
            'authManager' => [... ],
            'ad' => [
                'class' => 'Edvlerblog\Adldap2\Adldap2Wrapper',
                'providers' => [
                    'default' => [
                        'autoconnect' => true,
                        'config' => [
                            'domain_controllers' => ['your.ldap.domain.com'],
                            'base_dn'            => "OU=XXX,OU=XXX,DC=ccccccc,DC=xxxx,DC=com",
                            'admin_username'     => "your_username",
                            'admin_password'     => "your_password",
                            'port'               => 389,
                        ],
                    ],
    
                ],
    
            ],
        ],