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:
Comments
0 responses to “Yii role mapping based on Active Directory”
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.