deny user login on backend

I have yii2 advanced template with RBAC migration applied. I was trying to learn RBAC and followed the Docs 2.0.

I have logged in with database. But the front end and backend both get logged in with any account. I have made 2 RBAC roles (admin, user). But cant understand or find how to restrict backend to be logged in by user-role.

The following is the code for roles:


namespace console\controllers;


use Yii;

use yii\console\Controller;


class RbacController extends Controller

{

    public function actionInit()

    {

        $auth = Yii::$app->authManager;


        // add "admin" role

        $admin = $auth->createRole('admin');

        $auth->add($admin);


        // add "user" role

        $user = $auth->createRole('user');

        $auth->add($user);


        $auth->assign($admin, 1);

    }

}


'rules' => [

    [

        'actions' => ['login', 'error'],

        'allow' => true,

    ],

    [

        'actions' => ['logout', 'index'],

        'allow' => true,

        'roles' => ['@'],

    ],

There are only 2 pages index and login in backend. If i do action=>[login, index, error] roles=>[admin]. It will not even view the login page, bcoz current user is guest. and according to the rule an admin role is required. i have tried it. and the problem is as i explained.

Either you need to allow all users to access the login page on the backend, otherwise your admin can’t login or you would need a login page on the front end with a link to take you to the back end after you have logged in as admin. An alternative method is to use IP address to restrict access to the back end but that might not work in your case. I would image the roles would be like this:


'rules' => [

    [

        'actions' => ['login', 'error'],

        'allow' => true,

    ],

    [

        'actions' => ['logout', 'index'],

        'allow' => false,

        'roles' => ['?'],

    ],

    [

        'actions' => ['logout', 'index'],

        'allow' => true,

        'roles' => ['admin'],

    ],

Thanks for reply, i have tried this and the problem is; it lets any user logs in & would give error that user-role cant access this page. And the problem is according to rules it won’t let the user-role log out. bcoz logout is allowed to admin-role.

This RBAC is so stupid. I was very convinced by all the hype of Yii as fastest best oop latest tech framework. but close to zero support, not handy documentation. Not even stackoverflow have answer for this.

I really want to learn the framework, but seems they don’t want to ^_^

The guide here: https://github.com/yiisoft/yii2/blob/master/docs/guide/security-authorization.md is quite good but the problem is not with yii but with understanding the business logic of your application.

It is not possible to block a role entering a page before you know who the user is. That’s nothing to do with Yii, that’s just rbac in every system. To me there is nothing wrong with allowing a normal user to attempt login and then tell them they can’t access the page, either by error page or by some other mechanism - they should not be entering that area anyway.

The two sides you need to think about are 1) Not offering links to users who should not see them and 2) Enforcing access control in case someone accesses a link directly.

If you really want a more slick system, then when the user attempts login, before you perform the real authentication, check manually with the auth manager whether yii::$app->authManager->checkAccess($userid, ‘admin’) and if not, fail the login.

I got bit further with ur suggestion. Thanks a lot.

What i have done is in backend/controller, i have modified the actionLogin() so that i can pass a parameter explaine user_role.




    public function actionLogin()

    {

        if (!\Yii::$app->user->isGuest) {

            return $this->goHome();

        }


        $model = new LoginForm();

        if ($model->load(Yii::$app->request->post()) && $model->login('admin')) {

            return $this->goBack();

        } else {

            return $this->render('login', [

                'model' => $model,

            ]);

        }

    }

And in commom/loginForm i have done so:


    

    public function login($USER_ROLE)

    {

        if($USER_ROLE == 'admin'){

            if ($this->getUser()->role != 20) {

                $this->addError('password', 'Incorrect username or password.');

                return false;

            }

        }


        if ($this->validate())

            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);

        else

            return false;

    }

Can u tell me if i’m going in right direction, or is there any better way.

I don’t think that will work as you have coded it because in login() you are checking the role on the current user but at this point, there is no user since you haven’t logged in.

Can you confirm that getUser() is a factory method that returns a user from the userid entered into the form? If it isn’t then you would need something more like:


if($USER_ROLE == 'admin'){

    $user = User::getUserForId($this->userid);


    if ($user->role != 20) {

    $this->addError('password', 'Incorrect username or password.');

                return false;

    }

}

I also think you should validate the form before you check for the admin role, not afterwards.


if ($this->validate())

{

    if ($USER_ROLE == 'admin') {

    // etc.

    return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);

}

else

{

    return false;

}

Hi, sorry 4 late reply. timezone difference.

Now i understand about RBAC bcoz u explained. I was not clear about its working. And you pointed me to right direction. I don’t like the idea of passing ‘admin’ as a parameter to login bcoz it seems odd to me, i hope i get to know a generic/dynamic way. otherwise i have to make diferent login function in controller. and there are simply to many user-roles to handle.

About the getUser(); Yes its builtin function in common/models/LoginForm/getUser();

And u are right that my admin check should be after Validation() check.

what validatin(), does is it validates checks on submited data and after that it calls the getUser(); saves it in loginForm->user object and after validation the login condition follows.

Now bcoz i know more about how RBAC work, i am looking for better solution bcoz i’m trying to learn a blog site with yii2. I just started learning frameworks and yii is already bit complex/hard for novice. though i have fair good knowladge of php & opp.

Heres the code defination of the function:




    /**

     * Finds user by [[username]]

     *

     * @return User|null

     */

    public function getUser()

    {

        if ($this->_user === false) {

            $this->_user = User::findByUsername($this->username);

        }


        return $this->_user;

    }