1
votes

I've followed the tutorial and all the CakePHP Authorization guide and I can't get my isAuthorized() method to be called. My understanding (correct me if I am wrong, which is incredibly likely) is by delegating authorize to the specific controllers by doing 'authorize'->['Controller'] in AppController.php, when a method in UsersController is called, in this case 'add', UsersController would run the isAuthorized() method I defined. I was testing to see if this method ran at all outputting a flash->error message right when isAuthorized() is called but nothing happens. If I explicitly call isAuthorized($hardcodeduser) in my beforeFilter()method it will work but only if I hard code a user.

The way the method is supposed to work is: If a registered user requests to add/create a new user, the system checks to see if the user has admin/staff level permissions (which is just a 0 or 1 value in the database) and if the user does not have permission then it redirects to the home screen with an error message that says "You are not authorized to access that function".

Any help or suggestions or other links to follow would be much appreciated!

class AppController extends Controller {

    public $components = ['Flash', 'Auth', 'Session'];

    public function initialize() {

        $this->loadComponent('Flash');
        $this->loadComponent('Auth', [
            'authorize' => ['Controller'],
            'loginRedirect' => [
                'controller' => 'Articles',
                'action' => 'index'
            ],
            'logoutRedirect' => [
                'controller' => 'Pages',
                'action' => 'display',
                'home'
            ]

        ]);
    }

    public function beforeFilter(Event $event) {
        $this->Auth->authorize = 'Controller';
    }

    public function isAuthorized($user) {

        if(isset($user['is_staff']))
            return true;

        return false;
    }
}


class UsersController extends AppController {

    public function beforeFilter(Event $event) {
        parent::beforeFilter($event);
        $this->Auth->allow(['logout']);
    }

    public function isAuthorized($user) {

        $this->Flash->error(__('Test Message PLEASE WORK'));
        if($this->request->action === 'add') {
            $isStaff = $user['is_staff'];
            if($isStaff == 0) {
                $this->redirect($this->Auth->redirectUrl());
                $this->Flash->error(__('Not authorized to access this function'));  
                return false;
            }
        }
        return parent ::isAuthorized($user);
    }
}
3
You have several more coding flaws in your code. One of them: that you forgot to "return" your redirects, and that any following code is not executed at all. And you really need to get your basics straight as ndm mentioned. - mark
I apologize for the format, I've never posted on stack before and did a poor and rushed job of copying code over. The spacing to do code blocks messed me up and I didn't realize it was so poorly displayed. By not being called I mean: when the UsersController function add is called, I was under the impression that isAuthorized() would be automatically called because of the 'authroize'=>'Controller' call in the appcontroller. I expected my test message to show up because I figured isAuthorized would be called but nothing shows up unless I explicitly call isAuthroized($user) in the beforefilter - vars91

3 Answers

9
votes

Generally your assumption is correct, Controller::isAuthorized() is going to be invoked automatically when using the controller authorization handler.

The problem with your code is that in your UsersController::beforeFilter() method you are explicitly allowing the add method to be accessed by everyone (it won't even require authentication):

$this->Auth->allow(['logout', 'add']);

You have to understand that once a method is allowed, there will be no further checks made by the auth component, see AuthComponent::startup().

Also note that you don't need to redirect and set a flash message manually, the component will do that for you, you just need to configure it appropriately using the authError and unauthorizedRedirect options, see Cookbook > Components > Authentication > Configuration options

8
votes

As we following the Cake blog tutorial, they made a little mistake, that function "isAuthorized" never be called. And I did take a time to research it. Solution is Adding this line when load component "Auth":

'authorize' => array('Controller'),

so the code should looks something like this:

$this->loadComponent('Auth', [
    'loginRedirect' => [
        'controller' => 'Articles',
        'action' => 'index'
    ],
    'logoutRedirect' => [
        'controller' => 'Pages',
        'action' => 'display',
        'home'
    ],
    'authorize' => array('Controller'),                
]);

Hope it help some one saving time :)

1
votes

From cakephp 3.x documentation: you can configure authorization handlers in your controller’s beforeFilter() or initialize() methods using an array:

// Basic setup
$this->Auth->config('authorize', ['Controller']);

// Pass settings in
$this->Auth->config('authorize', [
'Actions' => ['actionPath' => 'controllers/'],
'Controller'
]);