This tutorial will show you how to manage user roles based on Active Directory information.
Step one – ad-ldap integration
Lets begin with ad-ldap integration download and install my Yii exstension yii-adldap.
Step two – prepare RBAC
For learning purposes I’ve selected simple RBAC based on a PHP file. Put this into your Yii config file:
// config/main.php // application components 'components'=>array( 'authManager'=>array( 'class'=>'CPhpAuthManager', ), ), |
Now it’s time to create application roles:
// data/auth.php return array ( 'domain_user' => array ( 'type' => 2, 'description' => 'Standard domain user', 'bizRule' => '', 'data' => '', ), 'administrator' => array ( 'type' => 2, 'description' => 'Domain administrator', 'bizRule' => '', 'data' => '', ), ); |
RBAC is ready, now you can set rules in controllers:
public function filters() { return array( 'accessControl', // perform access control for CRUD operations ); } /** * Specifies the access control rules. * This method is used by the 'accessControl' filter. * @return array access control rules */ public function accessRules() { return array( // allow everything to administrator role array('allow', 'roles'=>array('administrator')), // alllow few actions to domain users array('allow', 'roles'=>array('domain_user'), 'actions'=>array('index', 'list')), // deny everything to everyone else array('deny', 'users' => array('*')) ); } |
Step three
Time to map domain information to application roles. Open a UserIdentity class and add this property to it:
// components/UserIdentity.php /** * @var array RBAC role mappings based on domain criteria. * @see authenticate */ private $_roleMappings = array( // based on a group 'domain_user' => array( 'samaccountname'=> array(), 'groups'=> array('Domain Users'), ), // based on an acccount name 'administrator' => array( 'samaccountname'=> array('jdoe'), 'groups'=> array(), ), // based on mutliple groups and users 'administrator' => array( 'samaccountname'=> array('jdoe', 'madonis'), 'groups'=> array('Domain Admins', 'Admins'), ), ); |
Modify authenticate method provided in a yii-ldap extension:
/** * Authenticates a user using Active Directory. * * @return boolean whether authentication succeeds. */ public function authenticate() { // alter search fields if needed if(isset(Yii::app()->params['adFields'])) $this->_fields = Yii::app()->params['adFields']; // authenticate if (Yii::app()->ldap->authenticate($this->username, $this->password)){ $this->errorCode = self::ERROR_NONE; // collect AD info about users $info = Yii::app()->ldap->user()->infoCollection($this->username, $this->_fields); $groups = Yii::app()->ldap->user()->groups($this->username); // alter id to domain account name $this->_id = $info->samaccountname; // export ad info to user session foreach($this->_fields as $field) $this->setState($field, $info->$field); // export groups array $this->setState('groups', $groups); // assign roles based on domain data $auth=Yii::app()->authManager; // assign roles foreach ($this->_roleMappings as $role => $criteria) { // assign per username if(in_array(strtolower($this->id), $criteria['samaccountname'])) { if(!$auth->isAssigned($role,$this->id)) { if($auth->assign($role,$this->id)) { Yii::trace("{$this->id} was assigned to role $role based on AD username", 'application.components.UserIdentity'); } } } // assign per group if(count(array_intersect($groups, $criteria['groups']))>0) { if(!$auth->isAssigned($role,$this->id)) { if($auth->assign($role,$this->id)) { Yii::trace("{$this->id} was assigned to role $role based on AD groups", 'application.components.UserIdentity'); } } } } Yii::app()->authManager->save(); } else { $this->errorCode = self::ERROR_PASSWORD_INVALID; } return !$this->errorCode; } |
Last step – validate result
If everything went right you can login into your app using domain credentials. Enable debug mode in your index file and search for traces looking like this:
2013/11/08 14:16:57 [trace] [application.components.UserIdentity] JDoe was assigned to role domain_user based on AD groups 2013/11/08 14:16:57 [trace] [application.components.UserIdentity] JDoe was assigned to role administrator based on AD username
If you’ll find them congratulations! You’ve just connected your app to Active Directory domain. Write a comment in case of a problem.
Download:
Do you have a Yii 2.0 version for this?
Hi,
Yes I will rewrite this but I need some time to learn Yii2.
Nice work! I’m very interested in a Yii2 example as well!
Dear Konrad,
Hope you haven’t given up on writing a Yii 2.0 version of this wonderful guide.
It would be great to have a tutorial like this for Yii2.