Authorization with rbac yii - yii

I am trying to understand authorization in rbac and getting confused a bit with a couple of things.
In the accessControl rules i am using roles as such:
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index', 'view'),
'roles'=>array('user'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'roles'=>array('author'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
'roles'=>array('admin'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
I am also using the following setup :
$auth = Yii::app()->authManager;
$auth->createOperation('createPost', 'create a post');
$auth->createOperation('readPost', 'Read a post');
$auth->createOperation('updatePost', 'update a post');
$auth->createOperation('deletePost', 'delete a post');
$role = $auth->createRole('user');
$role->addChild('readPost');
$role = $auth->createRole('author');
$role->addChild('user');
$role->addChild('createPost');
$role = $auth->createRole('admin');
$role->addChild('author');
$role->addChild('updatePost');
$role->addChild('deletePost');
$auth->assign('user', 3);
$auth->assign('author', 2);
$auth->assign('admin', 1);
$auth->save();
There are 4 different operations with names (createPost, deletePost , readPost, udpatePost). However in the controller the action names are different such as actionIndex, actionView, actionCreate, actionDelete, actionUpdate and actionAdmin.
Questions:
How are operations being mapped to controller actions.
Should more operations be created such as IndexPost, ViewPost etc ..?
While using rbac, should we still keep the accesscontrol filter and rules as I have done here?
I am not sure if I am doing it right. Lots of confusion and lost. Please shed some light. Cheers.

They aren't being mapped, in each action you need to check this manually
if (Yii::app()->authManager->checkAccess('updatePost'))
thorow new HttpException(404);
Your can create IndexPost, ViewPost if some user can't see these actions.
In accessControl you can keep only check that user is logged, when it's needed.
For more information check this articles: Simple RBAC, Getting to Understand Hierarchical RBAC Scheme

Related

Yii Rights :: Error 403 You Are Not Authorized To Perform This Action

I am newb in yii. I installed yii-rights in protected/modules/rights as per documentation. But can't use properly. There are something missing that I couldn't find out. localhost/index.php/right page is working well. But when I press on "permissions", "roles", "tasks", "operations". It shows
"Error 403
You are not authorized to perform this action."
Here is my main config::
'import'=>array(
'application.modules.right.*',
'application.modules.right.models*',
'application.modules.rights.components.*',
),
'rights'=>array(
'superuserName'=>'Admin', // Name of the role with super user privileges.
'authenticatedName'=>'Authenticated', // Name of the authenticated user role.
'userIdColumn'=>'id', // Name of the user id column in the database.
'userNameColumn'=>'username', // Name of the user name column in the database.
'enableBizRule'=>true, // Whether to enable authorization item business rules.
'enableBizRuleData'=>false, // Whether to enable data for business rules.
'displayDescription'=>true, // Whether to use item description instead of name.
'flashSuccessKey'=>'RightsSuccess', // Key to use for setting success flash messages.
'flashErrorKey'=>'RightsError', // Key to use for setting error flash messages.
'baseUrl'=>'/rights', // Base URL for Rights. Change if module is nested.
'layout'=>'rights.views.layouts.main', // Layout to use for displaying Rights.
'appLayout'=>'application.views.layouts.main', // Application layout.
'cssFile'=>'rights.css', // Style sheet file to use for Rights.
'install'=>false, // Whether to enable installer.
'debug'=>false,
),
'components'=>array(
'user'=>array(
'class'=>'RWebUser',
// enable cookie-based authentication
'allowAutoLogin'=>true,
'loginUrl'=>array('/user/login'),
),
AssignementController
public function accessRules()
{
return array(
array('allow', // Allow superusers to access Rights
'actions'=>array(
'view',
'user',
'revoke',
),
'users'=>$this->_authorizer->getSuperusers(),
),
array('deny', // Deny all users
'users'=>array('*'),
),
);
}
I need your help. PLEASE
Note that:: I am using yii-user also. yii-user is working well.
In your controller, you are required to name your action to perform function.
public function accessRules(){
.......
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update','districts','center'),
'users'=>array('#'),
......
}
For example in the above code, district and center are actions.
Hopefully, you will get the idea.
I know it's an older question but have you add
public function filters()
{
return array(
'accessControl',
);
}
to the AssignementController? Yii needs it to regard function accessRules() for access controlling.
Set your "Yii::app()->user->name";
Try this
<?php
class UserIdentity extends CUserIdentity
{
protected $_id;
const USER_INACTIVE = 3;
public function authenticate()
{
$p= Person::model()->findByUsername($this->username);
if (empty($p))
$this->errorCode = self::ERROR_USERNAME_INVALID;
elseif (!CPasswordHelper::verifyPassword($this->password, $p->password))
$this->errorCode = self::ERROR_PASSWORD_INVALID;
else
{
$this->_id = $p->id;
$this->username = $p->username;
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}
public function getId() {
return $this->_id;
}
}
the line "$this->username = $p->username;";
Hope this help.

Specifying Access Rules Specific Error Message In Controller

I am currently using yii 1.1.10 version in which I am trying to specify rules specific error message by defining message in accessRules function as specified below:
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('xxx','yyy'),
'users'=>array('*'),
),
array('allow', // allow all users to perform 'index' and 'view' actions
'message'=>'You must be logged in as Member to perform this action.',
'actions'=>array('zzz','aaa',),
'expression'=>'AuthenticationHelper::isSessionUserAdmin()',
),
array('deny', // deny all users
'users'=>array('*'),
'message' => "This is a generic message.",
),
);
}
However in case expression fails, I am able to view only message that has been specified against deny rule which is "This is a generic message.", even when second evaluation fails. Any points to achieve desired behaviour is highly appreciated.
You can propably do it this way:
array('allow',
'message'=>'You must be logged in as Member to perform this action.',
'actions'=>array('zzz','aaa',),
'expression'=>'AuthenticationHelper::isSessionUserAdmin()',
),
array('deny',
'message'=>'You must be logged in as Member to perform this action.',
'actions'=>array('zzz','aaa',),
'expression'=>'!AuthenticationHelper::isSessionUserAdmin()',
),

Multiple identity properties for authentication in ZF2 with Doctrine 2

I have login form with input text fields:
Group Name
User Name
User Password
I have two tables
groups
id
name
users
id
name
group_id
I have its mapping entities and associations.
But user name not unique within table users, because different groups can include users with equal names. Therefore i need:
find group by name in table groups
find user by name in table users with condition where group_id=<group_id>
How to do it correctly in Zend Framework 2 using Doctrine 2?
All official documentation and examples depict situation, where identity property is single column (example).
Sorry for my bad language. Thanks.
Instead of making my own implementation of Doctrine's authentication services i decide to implement it via form validation inside isValid() method of my authentication form.
Example:
<?php
namespace My\Form\Namespace;
use Zend\Form\Form;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\InputFilter\InputFilterProviderInterface;
class Auth extends Form implement InputFilterProviderInterface
{
protected $_em;
public function __construct(ServiceLocatorInterface $sm)
{
parent::__construct('auth');
// inject Doctrine's Entity Manager
$this->_em = $sm->get('Doctrine\ORM\EntityManager');
// login field
$this->add(...);
// password field
$this->add(...);
// group_name field
$this->add(...);
}
public function getInputFilterSpecification()
{
//Input filter specification here
...
}
public function isValid()
{
/*
* input filter validations
*/
if (!parent::isValid())
return false;
/*
* group exists validation
*/
$group = $this->_em
->getRepository('<Group\Entity\Namespace>')
->findOneBy(array(
'name' => $this->get('group_name')->getValue(),
));
if (!$group){
$this->get('group_name')
->setMessages(array(
'Group not found',
));
return false;
}
/*
* user exists validation
*/
$user = $this->_em
->getRepository('<User\Entity\Namespace>')
->findOneBy(array(
'group_id' => $group->getId(),
'name' => $this->get('login')->getValue(),
));
if (!$user){
/*
* It's not good idea to tell that user not found,
* so let it be password error
*/
$this->get('password')
->setMessages(array(
'Login or password wrong',
));
return false;
}
/*
* password validation
*/
$password = $this->get('password')->getValue();
// assume that password hash just md5 of password string
if (md5($password) !== $user->getPassword()){
$this->get('password')
->setMessages(array(
'Login or password wrong',
));
return false;
}
return true;
}
}
Inside controller it is enough to call $form->isValid() to make sure that user entered correct authentication data.
I have the same problem.
I have to do two authentications in same application, because my boss doesn't wanna two databases. So, I had to make two user tables and two login pages.
One route to admin -> /admin/login
And the front-end for other users -> /login
I've tried to put on more authenticate in doctrine authentication array but it didn't work.
I think I'll open a issue on doctrine github page.

What is main purpose of filter in YII?

As as title clarifies what is main purpose of filters in Yii? I am newbie to Yii and little confuse about filters and validators? Any one can explain it for me?
A validator will be validating that an attribute in a model is as it should be: an, integer, a date, less than a given size, ...
Example:
public function rules()
{
return array(
//username and password are required
array('username, password', 'required'),
//myInt is a number between 0 and 255
array('myInt', 'numerical', 'min'=>0, 'max'=> 255),
);
}
The validation rules will be tested when calling $model->validate() or $model->save(). If one of the validator did not pass, then an error will be thrown to the user.
You can know the errors thrown by calling $model->getErrors()
Source: Model Rules Validation
The filter definition is :
A filter can be applied before and after an action is executed. It can
modify the context that the action is to run or decorate the result
that the action generates.
So basiclly it will execute some work before calling the controller method (so before rendering anything on the screen) or after the controller is done (so it could be after the datas are validated and added in the db).
As example we can say:
Check user authorizations
Implements HTTP caching
...
To apply filters to actions, we need to override the CController::filters() method. The method should return an array of filter configurations. For example,
public function filters()
{
return array(
'postOnly + edit, create',
array(
'application.filters.PerformanceFilter - edit, create',
'unit'=>'second',
),
);
}
Using the plus and the minus operators, we can specify which actions the filter should and should not be applied to. In the above, the postOnly filter will be applied to the edit and create actions, while PerformanceFilter filter will be applied to all actions EXCEPT edit and create. If neither plus nor minus appears in the filter configuration, the filter will be applied to all actions.
Source: Yii API about CFilter and Yii Guide
So if you want to validate some datas, then use the validators and if what you want to do is not depending on the model (ie check a user is logged in, ...) then you should implements a filter.
In general the difference between a filter and a validator is pretty obvious.
Validators are used for preventing inserting or updating wrong data in db. Filters could be used to make some preparation before or after validating
class LoginForm extends CFormModel
{
public $mail;
public $password;
public $rememberMe;
public function rules()
{
return array(
array('mail, password', 'filter'=>'trim'),
array('mail', 'filter'=>'mb_strtolower'),
array('mail, password', 'required'),
array('mail', 'email'),
array('rememberMe', 'boolean'),
array('password', 'authenticate'),
);
}
}
Filters is mainly used to filter your URL. Here also included accessControl. That's means when you set URL to access any action. Then those filter checked that action is permitted for those User or not. Also if you set that this controller delete action only can be accessible by POST method Then you will not be able to delete by using GET method. Those all type of access .... Controlled by FILTERS.
On the other hand, Validator is used to validate your any input filed AS your wishes. As like Minimum , Maximum, Integer or not, is it will be Unique or not, is this field required or not. is this field will be email type or not ...... and many more type of validation of INPUT FIELD.....
In Single Word it can be say " Validator is used for Input Validation and Filter is Used for Output Validation "

Yii framework not checking roles in accessRules

I am creating some kind of admin panel in Yii framework, and im setting state at login like this
public function authenticate()
{
$record=AdminTbl::model()->findByAttributes(array('usr'=>$this->username));
if($record===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($record->pwd!==$this->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$record->id;
$this->setState('roles','main');
$this->errorCode=self::ERROR_NONE;
}
return !$this->errorCode;
}
I checked if state was really set, echoed out on view. Later i put that role in accessrules()
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view','create','update','admin','delete'),
'roles'=>array('main'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
And i can't access those pages with this user logged in. What is the problem ?
Have a look here, http://www.yiiframework.com/doc/guide/1.1/en/topics.auth
You need to create the main role and assign it via the user id.
If you need simple Role based access control without the long RBAC process then this article is just for you
http://www.yiiframework.com/wiki/328/simple-rbac/