yii

Yii role mapping based on Active Directory

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:

Published by

Konrad Fedorczyk

Konrad Fedorczyk

I'm interested in programming and gamedev. I especially luv HTML5 and everything connected to web technologies.

5 thoughts on “Yii role mapping based on Active Directory”

Leave a Reply

Your email address will not be published. Required fields are marked *