CakePHP: How do I access the Auth->allow action array? - cakephp

I've been working on an application using CakePHP 2.6. We have a class called AuthUser which builds upon the functionality of AuthComponent and allows us to check permissions against our roles for sections in our database.
However I have noticed that our "isAuthorised" function ignores the $this->Auth->allow() which means actions that shouldn't need authorisation are being caught by our checks and this needs to be updated to check properly.
Is it possible to access the $this->Auth->allow() array of actions and if so how would someone go about accessing it?
Below I have included the "isAuthorised" function from the AuthUser class:
public function isAuthorised($controllerName = null) {
//Admin has access to everything
if (AuthUser::isAdmin() === true) {
return true;
}
$roles = array();
//Get the roles allowed for the section
$results = AppController::runStoredProcedure('spGetCurrentSectionRolesForSectionBySectionName', array( $controllerName ));
if (isset($results) && is_array($results)) {
foreach ($results as $row) {
if (isset($row['RoleName'])) {
array_push($roles, $row['RoleName']);
}
}
}
//Check if authenticated user has permission to current controller (is one of the allowed roles)
$userRoles = AuthComponent::user('role');
if (isset($userRoles) && is_array($userRoles)) {
foreach ($userRoles as $key => $value) {
if ($value == true) {5
if (in_array($key, $roles)) {
return true;
}
}
}
}
return false;
}

Please try this
pr($this->Auth->allowedActions);
This will list you all auth->allow() function name that are defined in $this->Auth->allow()

Related

Cannot Authenticate user in Cake PHP 4.1

I have setup latest cake ph setup and when I try to login user it gives me this error
Argument 1 passed to Cake\Http\Session::_overwrite() must be of the type array, null given
My code is
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Username or password is incorrect'));
}
When I check $user it gives me the identified user but later it gives me above error.
Remove array type in Session.php in _overwrite function in vendor. as shown below code.
It's work for me.
/vendor/cakephp/cakephp/src/Http
protected function _overwrite( &$old, array $new): void{
if (!empty($old)) {
foreach ($old as $key => $var) {
if (!isset($new[$key])) {
unset($old[$key]);
}
}
}
foreach ($new as $key => $var) {
$old[$key] = $var;
}
}

How to use unauthorizedRedirect to redirect user of different role to their respective page?

In my app I have a user with 3 different roles and each one with their own respective page that they can visit. I would like to redirect them to their own respective home page when they try to access any pages that they should not be viewing, but are unable to do so.
I found the below thread with a very similar problem, but after modifying and putting the code in AppController::beforefilter, I am unable to get the desired result.
How to redirect each type of user to a different page when access is denied?
Updated with code from the thread above:
public function beforeFilter(Event $event)
{
$user_role = $this->Auth->user('role');
if ($user_role == "admin")
{
$redirectController = 'Pages';
$redirectMethod = 'adminhome';
}
elseif ($user_role == "teacher")
{
$redirectController = 'Pages';
$redirectMethod = 'teacherhome';
}
elseif ($user_role == "studentparent")
{
$redirectController = 'Pages';
$redirectMethod = 'parenthome';
}
$this->Auth->unauthorizedRedirect = array(
'controller' => $redirectController,
'action' => $redirectMethod,
'prefix' => false
);
}

page getting rendered after restrict drupal

I am using a custom module to restrict a role to a url in drupal 7 the code is as follows:
<?php
// Implements hook_init()
function restrict_access_init() {
$restrictions = restrict_access_restrictions();
global $user;
foreach ($restrictions as $path => $roles) {
// See if the current path matches any of the patterns provided.
if (drupal_match_path($_GET['q'], $path)) {
// It matches, check the current user has any of the required roles
$valid = FALSE;
foreach ($roles as $role) {
print implode("','",$user ->roles);
if (in_array($role, $user->roles)) {
$valid = TRUE;
break;
}
}
if (!$valid) {
drupal_access_denied();
}
}
}
}
function restrict_access_restrictions() {
// This array will be keyed by path and contain an array of allowed roles for that path
return array(
'path/path' => array('admin'),
);
}
?>
This does restrict access just fine but it then renders the page un-styled after the footer.
Any ideas why this may be happening?
I'm at a lost end with this now.
i needed to add module_invoke_all('exit'); exit(); under drupal_acess_denied();
e.g.
drupal_acess_denied();
module_invoke_all('exit');
exit();

update Auth session

How to update user information stored in auth session? without logout and login again.
I think this function will do it.. but is it the best-practice?
function update($field, $value){
$this->Session->write($this->Auth->sessionKey . '.' . $field, $value);
}
Yes.
You could grab the current info array, modify it, and then call $this->Auth->login($newUserData);, but this will also renew the session (no user interaction needed, though). Note: Applies to CakePHP 2.0+ only.
I've completed update function to get an array of new values. with keys (field name):
public function update($fields, $values = null) {
if (empty(parent::$_user) && !CakeSession::check(parent::$sessionKey)) {
return false;
}
if (!empty(parent::$_user)) {
$user = parent::$_user;
} else {
$user = CakeSession::read(parent::$sessionKey);
}
if (is_array($fields)) {
if (is_array($values)) {
$data = array_combine($fields, $values);
} else {
$data = $fields;
}
} else {
$data = array($fields => $values);
}
foreach ($data as $field => $value) {
if (isset($user[$field])) {
$user[$field] = $value;
}
}
return $this->login($user);
}
(thanks to tigrang for login function)

isAuthorized redirect URL cakephp

When isAuthorized = false the user is redirected to '/' is there a way to change this. I want to redirect to the user dashboard (/users/dashboard) with a flash message saying 'Access prohibited' or something like that.
Cheers!
public function isAuthorized($user) {
if (isset($user['role']) && $user['role'] === 'admin') {
return true; //Admin can access every action
}
return false; // The rest don't
}
If your isAuthorised variable is being evaluated in your controller.
You can call the redirect function.
$this->redirect(array('controller' => 'users', 'action' => 'dashboard'));
If you are actually inside the users controller allready, just call
$this->redirect(array('action' => 'dashboard'));
If not, where are you checking the isAuthorised value?
This is not an ideal solution. However it seems that there is no way to do this with the current built in AuthComponent
Edit: Added code as an example.
public function isAuthorized($user) {
if (parent::isAuthorized($user)) {
return true;
}
// Authorised actions
if (in_array($this->action, array('dashboard'))) {
return true;
}
// Will break out on this call
$this->redirect(array('controller' => 'users', 'action' => 'dashboard'));
return false;
}
I think the best way is to use exception and extends like that :
AppController.php
public function isAuthorized($user) {
throw new ForbiddenException(__('You are not authorized to access.'));
}
AnotherController.php
public function isAuthorized($user) {
if (isset($user['role']) && $user['role'] === 'admin') {
return true;
}
return parent::isAuthorized($user);
}
With this code you are able to manage the roles and the error.
If they are being logged out you can send them where you want with:
$this->Auth->logoutRedirect
I would personally use:
$this->Auth->authError = "You are not authorized to access.";
In order to redirect them to root with a flash message notifying them of the error.
Is a wrong behavior of AuthComponent.
In a nutshell: if the url is visited by a link, the framework is able to reconstruct the path and then redirect to the referring page. Otherwise (by direct entry into a url bar) it fails and it redirects to the home page.
The "bug" is documented and it will be corrected in a future release.
See: http://cakephp.lighthouseapp.com/projects/42648/tickets/591-inconsistent-redirect-behaviour-by-auth-acl
I do a little better than #deep55.
isAuthorized() method can throw an exception no problem, but i think that the inheritance of the Controllers would permit us to improve authorization algorithm using first AppController.isAuthorized(), not last.
So, here is my solution, assuming that I use a user model called Utilisateur, and a role model called Role.
AppController :
/**
* Parent method
*/
public function isAuthorized($user){
App::uses('Utilisateur','Model');
$User = new Utilisateur();
$isAdmin = $User->hasRole(10,$user['id']);
if ($isAdmin) {
return true;
}
}
/**
* Reject unauthorized actions
*/
public function rejectRequest(){
$errorMessage = __("Sorry, you can't do this.");
if ($this->isRest()) {
throw new ForbiddenException($errorMessage);
} else {
$this->Auth->authError = $errorMessage;
$this->Auth->flash['params']['class'] = 'alert-danger';
}
return false ;
}
Utilisateur model :
/**
* hasRole method return true if the user belongs to the correct role group
*/
public function hasRole($role_id, $user_id){
if (!isset($user_id)) {
if (!empty($this->id)) {
$user_id = $this->id ;
} else throw new Exception("Error, parameter $user_id is missing", 1);
}
$user = $this->find('first',array(
'conditions' => array('Utilisateur.id' => $user_id),
'fields' => array('id'),
'contain' => array('Role.id')
));
$roles = $user['Role'];
foreach ($roles as $r) {
if ($role_id == $r['id']) {
return true;
}
}
}
And last, in a specific controller :
/**
* Child method
*/
public function isAuthorized($user){
if (parent::isAuthorized($user)) {
return true;
}
if ( false ) {
return true ;
}
if ( false ) {
return true ;
}
return $this->rejectRequest() ;
}
For Cake version 2, as written in documentation for AuthComponent:
AuthComponent::$unauthorizedRedirect
Controls handling of unauthorized access. By default unauthorized user is redirected to the referrer URL or AuthComponent::$loginRedirect or ‘/’. If set to false a ForbiddenException exception is thrown instead of redirecting.
you can configure AuthComponent to redirect you to custom page in one place using unauthorizedRedirect property.
Just set it in the place where you configure Auth as a component
'Auth' => array(
... other settings...,
'unauthorizedRedirect' => '/users/dashboard'
)
After being redirected, you can print error message defined by authError property
echo $this->Session->flash();
echo $this->Session->flash('auth');
but it will be the same message for any authentication or authorization error.

Resources