Yii2 ldap identity set up after authentication

Nan picture Nan · May 5, 2015 · Viewed 7.8k times · Source

I am newbie with Yii2 and I need to create a login system using ldap. There is not much information about it so I hope somebody can help me.

I installed edvlerblog/yii2-adldap-module and I already succeed with the authentication implementation.

My problem is that I want, after login, have the identity of the user the same way as it is working with the advanced template and be able to use the Yii::$app->user functionality.

The official example creates User which implements IdentityInterface but through ActiveRecord:

http://www.yiiframework.com/doc-2.0/yii-web-identityinterface.html

I also found many examples referring to Yii version 1. This is a good one:

https://www.exchangecore.com/blog/yii-active-directory-useridentity-login-authentication/

But still not able to make it work... Probably is a concept problem or a syntax issue, but anyway I would really appreciate some help here.

models/LoginForm.php authentication method:

public function validatePasswordLdap($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUserLdap();
        if (!$user || !Yii::$app->ldap->authenticate($this->username,$this->password)) {
            $this->addError($attribute, 'Incorrect username or passwords.');
        }
    }
}

models/LoginForm.php login method:

public function loginLdap()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUserLdap(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    } else {
        return false;
    }
}

and the last one, the getUser method. UserLdap is implenting IdentityInterface but I don't know how to do it correctly:

public function getUserLdap()
{
    if ($this->_user === false) {           
        $this->_user = UserLdap::findIdentity($this->username);
    }

    return $this->_user;
}

Answer

Nan picture Nan · May 6, 2015

I understood the logic of that finally:

  • When you login in the view the LoginForm.php, takes the username and password and validates using validatePasswordLdap. You have to specify in the rules which function is validating the password.

  • Then if validate() is OK, it calls FindIdentity with the username introduced in the login. This function has to return an IdentityInterface object so first you need to create the User object, set the parameters (email, telephone, name,..) and return it.

  • To user the login/logout functionality and the isGuest throughout the site, you just have to do as loginLdap function below and pass this user object to the Yii::$app->user->login method.

The code looks like this:

LoginForm.php

public function rules()
{
    return [
        // username and password are both required
        [['username', 'password'], 'required'],
        // rememberMe must be a boolean value
        ['rememberMe', 'boolean'],
       // password is validated by validatePassword()
        ['password', 'validatePasswordLdap'],
    ];
}


public function validatePasswordLdap($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUserLdap();
        if (!$user || !Yii::$app->ldap->authenticate($this->username,$this->password)) {
            $this->addError($attribute, 'Incorrect username or passwords.');
        }
    }
}

public function loginLdap()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUserLdap(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    } else {
        return false;
    }
}

User.php

public static function findIdentity($id)
{

    $new_identity = new User();

    if ($user_ldap_info = Yii::$app->ldap->user()->infoCollection($id, array("*"))){
        $new_identity->setId($user_ldap_info->samaccountname);
        $new_identity->setEmail($user_ldap_info->mail);
        $new_identity->setUsername($user_ldap_info->displayName);   
    }

    return $new_identity;
}

public function setEmail($email)
{
    $this->email = $email;
}

public function setUsername($username)
{
    $this->username = $username;
}

public function setId($id)
{
    $this->id = $id;
}

Inside LoginForm.php

public function getUserLdap()
{
    if ($this->_user === false) {           
        $this->_user = User::findIdentity($this->username);
    }

    return $this->_user;
}

EDIT: due to vendor ADLDAP update I had to change the findIdentity to this:

public static function findIdentity($id)
{
    $new_identity = new User ();

    if ( $user_ldap_info = Yii::$app->ldap->users()->find($id) ) {
        $new_identity->setId ( $user_ldap_info->samaccountname [0] );
        $new_identity->setEmail ( $user_ldap_info->mail[0] );
        $new_identity->setUsername ( $user_ldap_info->givenname [0] );
    }

    return $new_identity;
}