PowerAuthComponent extends CakePHP’s AuthComponent adding a $accessDeniedRedirect property to allow define a static redirect when an access deny happen to an authenticated user.
Usage:
You can use this class by aliasing the standard AuthComponent inclusion in your AppController (or wherever you plan to use Authentication and Authorization):
public $components = array(
'Auth' => array(
'className' => 'CakePower.PowerAuth',
'loginAction' => ...
);
);
You don’t need anything else code to implement this CakePower component!
NOTICE: if you are extending CakePowerController in your AppController you do not need to set up the “className” property. CakePower sets up the alias for you!
Why do I need PowerAuth?
CakePHP’s AuthComponent redirects to the referral url (fallback to the root url) when access is denied to an authenticated user but this behavior may falls into infinite loop if booth referral url and root action are denied to the user.
The stage:
Figure you have a fully protected app where even the root url (/) belong to authentication and authorization.
If your app is a private blog (like in CakePHP tutorials) you may have these controllers:
- posts – display and manage posts
- users – manage users
- info – display some analytics about the blog.
Authentication uses UsersController::login() and UsersController::logout() methods to handle users authentication so these actions are allowed in the AppController rules:
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginAction' => array( 'controller'=>'users', 'action'=>'login' ),
'authorize' => 'Controller'
);
public beforeFilter() {
// All app actions are protected except login/logout.
$this->Auth->allow( 'login', 'logout' );
}
}
Users Access Policies:
- User “Marco Sheeptaker” has an “admin” role so hes access is unlimitet.
- User “Analytics Hero” can access only the AnalyticsController in the app.
These rules are coded as follow in AppController::isAuthorized() method:
public function isAuthorized( $user ) {
if ( $user['role'] == 'admin' ) return true;
if ( $this->request->params['controller'] == 'analytics' ) return true;
return false;
}
When Authorization will cause a loop?
When “Marco Sheeptaker” login to the app no error happen: when authenticated his profile will know no restrictions in the app.
But what happen when an Analytics Hero user try to login?
- access the root url (/) via browser’s url bar
- authentication redirects to the login action
- when login success Auth redirects to the url requested before the login: the root url
- user is not allowed to view this url so he is redirected to the login another time!
Each login will redirect back… to the login! This is a loop!
Now the user understand he can’t go out this loop so he go to the root url by digit it into the browser’s url bar:
- access the root url (/) via browser’s url bar – user is already authenticated
- authentication return “true” so there is no login redirection rules
- authorization return false so user is redirected to the referral
- referral does not exists because of user has directly accessed the root url
- AuthComponent fallback for the referral url is… the root url!!!
- user is redirected to the root!
This will cause a “bad redirection error” in (modern) browser! In ancient browsers (aka IE<9) it will crash down the client because of an infinite loop!!!
What do PowerAuthComponent does for me?
In simplest configuration (as shown at the beginning of this page) PowerAuthComponent replace fallback url for the referral url when redirecting after an access denied event. In place of the root url (/) it will use the loginAction property.
This way every infinite loops are kicked out of the application! If an action is denied and even the root action is denied PowerAuthComponent will redirect to the login page!
$accessDeniedRedirect
You can customize this behavior by setting an $accessDeniedRedirect. This property will be used in place of the $loginAction when configuring the referral’s fallback url:
public $components = array(
'Auth' => array(
'className' => 'CakePower.PowerAuth',
'loginAction' => ...
'accessDeniedRedirect' => array( 'controller'=>'pages', 'action'=>'access_denied_error' )
);
);
$accessDeniedHardRedirect
If you want to skip the referral url and force redirection to an error page you can set the $accessDeniedHardRedirect propety.
This way when an action is not allowed the PowerAuthComponent will always redirect to defined url:
public $components = array(
'Auth' => array(
'className' => 'CakePower.PowerAuth',
'loginAction' => ...
'accessDeniedHardRedirect' => array( 'controller'=>'pages', 'action'=>'access_denied_error' )
);
);
Bibliography & Resources: