We are going to deploy the new yiiframework.com website on March 23, 2018 from 8:00 to 12:00 UTC.
Website and Yii documentation will not be available in this time frame. Check the news for more details.

Difference between #6 and #5 of Getting to Understand Hierarchical RBAC Scheme

Getting to Understand Hierarchical RBAC Scheme
hierarchy, RBAC, security, understanding
and Authorization</a> is a good tutorial. Among other topics, it describes
basic aspects of Yii's RBAC implementation. But however hard I read the
tutorial, I couldn't understand <i>how exactly</i> the hierarchy
works. I found how to define authorization hierarchy, how business rules are
evaluated, how to configure authManager, but almost nothing about how I should
build my hierarchy, in what sequence its nodes are checked, when the checking
process stops and what would be the checking result.

There was no other way for me but to dig into Yii's code and I would like to
present my findings in this article. I have to mention that digging in Yii's
code is not difficult at all, it's well-structured and everyone can do it, but
the following info can save you a bit of time particularly when you're a Yii

I must say it would be much easier for you to understand the article if you got
familiar with the above-mentioned tutorial especially with the topics starting
from <a
Access Control</a>.

Let's consider the hierarchy example from the tutorial (this example illustrates
how security can be built for some blog system):

$auth->createOperation('createPost','create a post');
$auth->createOperation('readPost','read a post');
$auth->createOperation('updatePost','update a post');
$auth->createOperation('deletePost','delete a post');
$task=$auth->createTask('updateOwnPost','update a post by author

First of all I'd like to convert this to a more human-readable form:

<table align="center" cellpadding="0"
cellspacing="0" class="tr-caption-container"
style="margin-left: auto; margin-right: auto; text-align:
<tr><td style="text-align: center;"><a
imageanchor="1" style="margin-left: auto; margin-right:
auto;"><img border="0"
<tr><td class="tr-caption" style="text-align:
center;">Sample blog system authorization
The <span style="background-color:
#9fc5e8;">turquoise</span> boxes represent roles, the <span
style="background-color: #ffd966;">yellow</span> box is a
task, and the most fine-grained level of the authorization hierarchy -
operations - are <span style="background-color:
#f9cb9c;">tan</span>. Collectively roles, tasks and operations are
called <b>authorization items</b>. You should keep in mind that
functionally all auth item types are equal. It's completely up to you to make
some auth item a role or a task - still it would do the same thing. Different
types of auth items are introduced solely for the purpose of naming convenience.
You are not limited to the three authorization levels: there can be multiple
levels of roles, tasks and operations. (Getting back to our diagram, you can see
this point illustrated by multiple levels of roles.) Also you may skip any of
these levels (the role <b>author</b> has immediate child operation
<b>create</b>). The only restriction is that in the auth hierarchy
roles should stay higher than tasks and tasks should stay higher than

Now let's take a quick look at what was on blog system creator's mind.
Everything seems to be quite logical. The weakest role is
<b>reader</b>: the only thing he is allowed to do is to
<b>read</b>. An <b>author</b> has a bit more power: he
also can <b>create</b> posts and <b>update his own</b>
posts. <b>Editors</b> can read posts and <b>update</b>
(edit) <i>all</i> posts, not own ones (in fact, according to the
hierarchy, editors can't create posts and that's why editors haven't got any
<i>own posts</i> at all). And of course, the most powerful role is
<b>admin</b> which can do anything.

If you are familiar with the principles of object-oriented hierarchy, your
former knowledge may lead you to a confusion. In every subsequent level of an
object tree, objects obtain (inherit) all (or part) of the features of their
parent (base) objects. This results in that bottommost objects are most
"loaded" with features, while the root objects have only basic
features. The opposite happens with RBAC hierarchy in Yii. The bottommost items
in the authorization hierarchy represent basic operations, while the topmost
authorization items (usually roles) are the most powerful and compound ones in
the whole authorization system.

So now that the idea behind the hierarchy is clear, let's understand how the
access checking works. To check if the current user as allowed to perform a
particular action, you should call the the <b>checkAccess</b>
method, for example:

    // create post

How our hierarchy is used by Yii to check the access? Although you are not
required to read this to understand the rest of the article, I provide here an
example piece of Yii's code responsible for access checking (an implementation
of CAuthManager for databases - CDbAutManager) for your reference:

 return false;
Yii::trace('Checking permission
  return true;
   return true;
 $sql="SELECT parent FROM {$this->itemChildTable} WHERE
as $parent)
   return true;
return false;

When you call <b>checkAccess</b>, Yii begins to recursively climb
along the authorization hierarchy and check each item's business rule. For
instance, when you make a call like this 


Yii first checks the <b>readPost</b>'s business rule (recall that an
empty business rule is equivalent to a business rule always returning
<b>true</b>). Then it searches for all <b>readPost</b>'s
parents - these are <b>author</b> and <b>editor</b> -
and checks their business rules as well. The process doesn't stop when a
business rule has been evaluated to <b>true</b>; it only stops when
some rule returned <b>false</b> or we have reached the top of the
hierarchy and there are no more parents to check.

So what are ways for the <b>checkAccess</b> method to return
<b>true</b>? They are two. First, the iteration can stop with a
positive result when Yii encounters in the hierarchy a so-called
<b>default role</b> - a role that is assigned by default to all
authenticated users. For our blog system this can be the
<b>reader</b> role. Default roles can be set up in the web app
configuration file; how this is done is described thoroughly in the <a
Default Roles</a> section of the tutorial.

The second way to make <b>checkAccess</b> return
<b>true</b> is explicitly creating an <b>authorization
assignment</b> which is basically defining an &lt;auth
item&gt;-&lt;user&gt; pair. In code, this can be done like this:


which is semantically equivalent to assigning roles to users. You're not limited
to assigning roles; individual tasks and operations can be assigned to users as
well. In real life, it is more practical not to hard code all auth assignments
but to store them in a database. You can implement this scenario using the
<b>CDbAuthManager</b> component which is described in the Yii

Let's get back to the <b>checkAccess</b> discussion. Before
hierarchy iteration begins, Yii collects all authorization items assigned to the
current user and at each iteration step checks if current hierarchy's auth item
is in the assignment list. If it is, the iteration stops and returns a positive

Assume we are implementing security for the "update post" user action.
Whoever is logged in into our blog system should pass our authorization check
before he is able to edit a post. Therefore the most appropriate place to check
the access is the beginning of the respective controller action:

public function actionUpdatePost()

 // ... more code

Suppose the current user is <b>Alice</b>. Let's see how Yii
processes the auth hierarchy. Although <b>updateOwnPost</b> is an
immediate parent of <b>updatePost</b> and returns
<b>false</b>, Yii quickly finds another parent auth item which
returns <b>true</b> - the <b>editor</b> role. As a
result, Alice gets a permission to do a post update. What happens if
<b>Bob</b> logs in? In this case the branch of the hierarchy going
through the <b>editor</b> item is also processed but no item along
it returns <b>true</b>. The only possible way for the access check
to succeed is then to go through the <b>updateOwnPost</b> item. 

But instead of an empty "always-true" business rule
<b>updateOwnPost</b> has a more complex one (see the first code
snippet at the beginning of the article) and for the evaluation it requires the
post creator's ID. How can we supply it to the business rule? In the form of
<b>checkAccess</b>'s parameter. To achieve this we need to modify
our controller action handler in the following way:

public function actionUpdatePost()
 // here we obtain $post, probably via active record ...

 if(!Yii::app()->user->checkAccess('updatePost', array('post'=>$post)))

 // ... more code

Note that despite <b>updateOwnPost</b> returns
<b>true</b> for <b>Bob</b>, the iteration through auth
hierarchy still goes on. It only stops and returns success when it reaches the
<b>author</b> item.

I think now you're able to figure out how Yii would check access given that
<b>Pete</b> or <b>John</b> logged in.

Returning to the above code snippet, it may seem that we're providing the
<b>post</b> parameter to the <b>updatePost</b> operation
whose business rule is empty and requires no parameters at all. This is truth
but not all of it. In fact Yii passes the same parameter set (there can be
several parameters as they are passed as an array) to every hierarchy item at
every iteration. If item's business rule requires no parameters, it simply
ignores them. If it does require them, it takes only those that it needs.

This leads to the two possible parameter passing strategies. The first one is to
remember for every auth item what other auth items can be reached from it in the
hierarchy and provide each call to <b>checkAccess</b> with the exact
number of parameters. The advantage of this strategy is code brevity and
probably efficiency. The other strategy is to always pass all parameters to
every auth item, no matter if they would actually be used for business rule
evaluation. This is a "fire-and-forget" method which can help to avoid
much of trial and error while implementing you app's security. Its downside is
possible code clutter and maybe drop in script performance.

This is only basic information about the RBAC authorization model in Yii; much
more advanced security models can be built using it. Please refer to <a
href="http://www.yiiframework.com/doc/guide/">The Definitive Guide
to Yii</a> and <a
Reference</a> for more details. Also there's a number of web interfaces
implemented as <a
which can help you do the Yii RBAC administration.
Write new article