0
votes

I have the following isAuthorized() function in my students controller:

function isAuthorized() {
    $studentId = $this->Auth->user('id');
    $studentEmail = $this->Auth->user('email');
    if ($this->Auth->user('active') == 1 && $this->Auth->user('level_complete') != 1) {
        $this->Auth->loginRedirect = '/classrooms/view';
        return true;
    } elseif (!$this->Student->hasPayed($studentId)) {
        $this->Session->write('Payment.student_id', $studentId);
        $this->Session->write('Payment.student_email', $studentEmail);
        $this->Session->write('Payment.examScore', $this->Student->getPlacementScore($studentId));
        $this->Auth->logout();
        $this->redirect(array('controller'=>'payments', 'action'=>'pay'));  
    } elseif ($this->Auth->user('level_complete') == 1) {
        $this->Session->write('Payment.student_id', $studentId);
        $this->Session->write('Payment.student_email', $studentEmail);
        $this->Auth->logout();
        $this->redirect(array('controller' => 'payments', 'action' => 'repay'));
    } else {
        $this->Auth->logout();
        $this->redirect(array('controller' => 'students', 'action' => 'disabled'));
    }


    return false;
}

Basically, there are four possible states covered in this method:

  1. The user is active and has not completed a level = Authorized
  2. The user has not payed = Not Authorized
  3. The user has completed a level and has to pay again = Not Authorized
  4. The user account is not active

The problem I am having is that I have a login form in my header, and I can login from any controller. If I login from a controller other than the Students Controller, the isAuthorized() method is not called, and the user can login even though he shouldn't be able to.

Any ideas?


Edit: After checking the API's definition of the isAuthorized() method, I think that the method is only called when actions from the students controller are requested. Where else could I implement this logic then? Thanks

2
Are you using beforeFilter() at all? - Jason McCreary
yeah setting up the Auth component in beforeFilter(), but not for this logic. I though that the isAuthorized() method was called when the user tried to log in. - AlexBrand
you have login action in every controller? - Anh Pham

2 Answers

5
votes

You're messing things up. The isAuthorized() method is called only when the user is logged in.

This mean that cake separates the logic in two parts:

1) the user must log to see access the action is controlled with the $this->Auth->allow() method (inside the beforeFilter of your controller). This tells cake if the user must log to see the action or not.

2) The User must pass the isAuthorized() method. Only if $this->Auth->authorize is set to "controller".

So, if you want that users must be logged in to access action "X" from Controller C, in your C Controller you must put this code:

function beforeFilter(){
    $this->Auth->authorize = 'controller';
    $this->Auth->allow('*');
}

After that, if you want to have more control over that (if the users role is "admin", for example) then you have to do that in your isAuthorized() method.

Hope it helps.

1
votes

I typically put such logic in my login() method of my Auth controller (i.e. UsersController).

However, I don't believe that your understanding of isAuthorized() is incorrect. Unfortunately I do believe it is more difficult to wire up.

For example:

  • As noted by santiagobasulto, you'll need to ensure you've configured Auth->authorize = 'controller'.
  • If you are using any beforeFilters() be sure you are calling parent::beforeFilter(). It's possible that you've forgotten this in a key area keeping Cake from ever reaching your functions on other login actions.