How can i change the default route when the user is logged? - cakephp

In my config.php file, this is the default router.
Router::connect('/', array('controller' => 'users', 'action' => 'signup'));
If users are not connected, they do not have the right to access to the edit actions and view action in the UsersController .
<?php
class UsersController extends AppController{
public $uses = array('User', 'Company', 'Town');
public function beforeFilter(){
parent::beforeFilter();
// If the user is not connected he can't access to these pages
$this->Auth->deny('view', 'edit');
}
}
When users use the login form and are logged in, they are redirected to the page controller and index action.
I would like that they can not enter (user and admin role) to the action signup of the controller Users.
Therefore changed the default route when the user is connected (either admin or user) . But i don't know in my case what i should do .
AppController :
<?php
class AppController extends Controller{
public $helpers = array('Text','Form','Html','Session','Cache');
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'pages', 'action' => 'index'),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
)
)
);
function beforeFilter(){
$this->Auth->loginAction = array('controller'=>'users','action'=>'login','admin'=>false);
//tell Auth to call the isAuthorized function before allowing access
$this->Auth->authorize = array('Controller');
//allow all non-logged in users access to items without a prefix
if(!isset($this->request->params['prefix'])){
$this->Auth->allow();
}
if(isset($this->request->params['prefix']) && $this->request->params['prefix'] == 'admin'){
$this->layout = 'admin';
}
// Si l'utilisateur est connecté
if (isset($this->Auth) && $this->Auth->user('id')) {
$this->layout = 'user';
}
}
function isAuthorized($user){
if(!isset($this->request->params['prefix'])){
return true;
}
$roles = array(
'admin' => 10,
'user' => 5
);
return false;
}
}
Thanks .

I found a way to do what I wanted without using ACLs but I do not know if this is the best solution and if it is safe, what do you think?
In Appcontroller in the action beforefilter ()
$role = $this->Auth->user('role');
if ($role == 'user' || $role == 'admin' && $this->request->params['controller'] == 'users' && $this->request->params['action'] == 'signup') {
$this->redirect(array('controller' => 'pages', 'action' => 'index'));
}

Related

CakePHP 2.x: Why is my /admin/user/login stuck in a redirect loop?

I have created a little project with an admin section. I am using admin routes to redirect to admin actions in my controllers. The website has pages that are available to everyone with no login required. To access the /admin or /admin/users, etc... You must login.
I have spread my admin actions across my controllers like "admin_login", "admin_users", ...
So my question is, when someone goes to /admin/users or some other adminpage, I have to check in each controller action if the user is in the session and otherwise redirect to thelogin form.
Is there a way to do this in one place? I used a beforefilter in my AppController class.
When using something like this, I get an infinite loop:
AppController.php
class AppController extends Controller {
public $helpers = array('Paginator','Acl.AclHtml');
public $components = array('Acl', 'Session',
'Auth' => array(
'authError' => 'You are not authorized to access that location.',
'authorize' => array(
'Actions' => array(
'actionPath' => 'controllers')
),
'controllers' => array('users')
));
public function beforeFilter() {
if(isset($this->request->prefix) && ($this->request->prefix == 'admin')){
$username = $this->Session->read('Admin.username');
if (empty($username)) {
$this->redirect (array(
'controller'=>'users',
'action'=>'login',
'admin'=>true
));
} else {
$this->redirect (array(
'controller'=>'admin',
'action'=>'dashboard',
'admin'=>true
));
}
}
// LDAP
$server_ip = $_SERVER['SERVER_ADDR'];
$ldapIp = ClassRegistry::init('LdapIp');
$ldapIpCount = $ldapIp->find('count', array('conditions' => array('ldap_ip' => $server_ip)));
if ($ldapIpCount >= 1) {
$this->Auth->authenticate = array('Ldap');
} else {
$this->Auth->authenticate = array('Form');
}
$this->Auth->authenticate = array('Form');
$this->Auth->allow();
if (!$this->Auth->isAllow($this)) {
$this->set(array(
'message' => array(
'text' => __('un aunthaticated request'),
'type' => 'error',
'status' => "401"
),
'_serialize' => array('message')
));
throw new ForbiddenException();
}
}
}
The front login with LDAP (Active directory).
UsersController.php
App::uses('AppController', 'Controller');
App::uses('Sanitize', 'Utility');
class UsersController extends AppController {
public $components = array('Paginator', 'Session', 'RequestHandler', 'Auth', 'Acl');
public function admin_login() {
$this->layout = 'admin_login';
if ($this->request->is('post')) {
$username = $this->request->data['User']['username'];
$password = $this->request->data['User']['password'];
$password = Security::hash($password, null, true);
$logged_in = $this->User->find('count', array('conditions' => array('User.username' => $username, 'User.password' => $password, 'User.role' => 'Admin', 'User.active' => 1)));
if ($logged_in >= 1) {
$this->Session->setFlash(__('Login successful!'), 'default', array('class' => 'alert alert-success'));
$users = $this->User->find('first', array('conditions' => array('User.username' => $username, 'User.password' => $password, 'User.role' => 'Admin', 'User.active' => 1)));
$this->Session->write('Admin.id', $users['User']['id']);
$this->Session->write('Admin.username', $users['User']['username']);
$this->Session->write('Admin.group_id', $users['User']['group_id']);
$this->Session->write('Admin.full_name', $users['UserProfile']['fname'] . " " . $users['UserProfile']['lname']);
$this->redirect(array('controller' => 'admin', 'action' => 'dashboard', 'admin' => true));
} else {
$this->Session->setFlash(__('Username or password is incorrect!'), 'default', array('class' => 'alert alert-error'));
}
}
}
public function admin_logout() {
$this->Session->delete("Admin");
//$this->Session->destroy();
$this->Session->setFlash(__('Logged out successful!'), 'default', array('class' => 'alert alert-success'));
$this->redirect(array('controller' => 'users', 'action' => 'login', 'admin' => true));
}
}
Yoy are getting an infinite loop because beforeFilter() will be called when you attempt to access /admin/users/login.
The proper way of dealing with your needs is setting up the Auth Component.
Once you've set up component, in UsersController::beforeFilter() you have to allow access to those actions that don't require login by means of the allow() method. E.g.
public function beforeFilter() {
$this->Auth->allow(array('signup'));
parent::beforeFilter();
}
This is also applicable to any other controller with actions that need to be accessed by non logged in users.
The loginAction you define in the Auth component configuration will be automatically allowed access.
In the blog tutorial you will find a good example of the Auth component usage.
Edit
As mentioned, AppController::beforeFilter() is always called, even when you try to access /admin/users/login. To prevent this from happening, try adding the following condition:
if (empty($username) && $this->action!='login') {
$this->redirect (array(
'controller'=>'users',
'action'=>'login',
'admin'=>true
));
}
You wouldn't need this if you allowed AuthComponent to take care of authentication for you.
Still, there's no guarantee that your code will work as expected. You are making your life difficult by not using AuthComponent to its fullest. I recommend that you research on the topic:
Creating Custom Authorize objects in the Cookbook 2.x
LdapAuth in cakephp 2.0 in Stack Overflow

CakePhp bad Auth redirection

I just started learning about the Auth component and I'm having a problem with redirection. The path of my local aplication is: localhost/school but when a logged user tries to acces to a url he isnt't allowed the site redirects to localhost/school/school and it says "The requested address '/school/school/' was not found on this server". I want no redirection when this happens, just show "you are not allowed" in the same page or maybe redirect to specific error page, how can I do that?. I have no problems with login or logout redirection, only what I said before. This is my App Controller:
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
//Configure AuthComponent
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login'
);
$this->set('current_user',$this->Auth->User());
$this->Auth->authError = "You're not allowed.";
}
I had the same problem and I solved it.
Try this code in AppController
public function beforeFilter() {
//Configure AuthComponent
// note just these two lines
$this->Auth->unauthorizedRedirect=FALSE ;
$this->Auth->authError="Access Denied";
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login'
);
$this->Auth->loginRedirect = array(
'controller' => 'posts',
'action' => 'add'
);
$this->Auth->allow('display');
//$this->Auth->allow();
}
class AppController extends Controller {
// added the debug toolkit
// sessions support
// authorization for login and logut redirect
public $components = array(
'Session','Flash',
'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authError' => 'You must be logged in to view this page.',
'loginError' => 'Invalid Username or Password entered, please try again.'
));
// only allow the login controllers only
public function beforeFilter() {
$this->Auth->allow('login');
}
public function isAuthorized($user) {
// Here is where we should verify the role and give access based on role
return true;
}
}
and in your controller it should be like this :
class UsersController extends AppController {
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('login','add');
}
public function login() {
//if already logged-in, redirect
if($this->Session->check('Auth.User')){
$this->redirect(array('action' => 'index'));
}
// if we get the post information, try to authenticate
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Flash->set(__('Welcome, '. $this->Auth->user('username')));
$this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->set(__('Invalid username or password'));
}
}
}
If you're not allowing someone access to a page, then what do you want the controller to do when they request it?
For example, you can set a redirect with :
$this->redirect(array(
'controller'=>'users',
'action' => 'login'));`
You can display a message using Session::setFlash();
localhost/projectName/projectName is a redirection when you don't have permission to this action. I had same problem. I comment for a moment 'Actions' => array('actionPath' => 'controllers') ) in $components. After that I set aros_acos by executing this code:
$group = $this->User->Group->read(null,'1');
$this->Acl->allow($group, 'controllers/Users/controlPanel');
After that I uncomment code, and in action 'controlPanel' and error disappear :) I don't know how I can change this redirection, but if I have record in aros_acos everything works.

Deny admin routes for specific and not logged users

I have two groups id :
Group 1 => Admins
Group 2 => Users
I'm looking for a way to deny the access for the users which are not admin (so group 2 and not logged) . The function isAuthorized doesn't work, i mean it's always return true, i just don't know why . Thanks for your help
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
parent::beforeFilter();
//Configure AuthComponent
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'home');
if(isset($this->request->params["prefix"]) && $this->request->params["prefix"] == "admin"){
$this->layout = "admin";
} else {
$this->layout = "default";
}
}
public function isAuthorized() {
parent::isAuthorized();
if(isset($this->request->params["prefix"]) && $this->request->params["prefix"] == "admin" && $this->Auth->user('group_id') === 1){
return true;
}
else {
return false;
}
}
}
PagesController
<?php
class PagesController extends AppController {
/**
* This controller does not use a model
*
* #var array
*/
public $uses = array();
/**
* Displays a view
*
* #param mixed What page to display
* #return void
* #throws NotFoundException When the view file could not be found
* or MissingViewException in debug mode.
*/
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow();
}
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
return $this->redirect('/');
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
try {
$this->render(implode('/', $path));
} catch (MissingViewException $e) {
if (Configure::read('debug')) {
throw $e;
}
throw new NotFoundException();
}
}
public function admin_index() {
$title_for_layout = 'Dashboard';
$this->set(compact('title_for_layout'));
}
}
routes
*/
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/admin', array('controller' => 'pages', 'action' => 'index', 'admin' => true));
To auto add prefix from action like admin_ you need to add the following line in your core.php file:
Configure::write('Routing.prefixes', array('admin'));
Then, the action PagesController::admin_index is accessible by /admin/pages/index instead of /pages/admin_index and the admin param is set to true so you can check it using $this->params['admin'] (see my code bellow).
Actually, in CakePHP all routes are denied by default but you allow all routes in PagesController by doing $this->Auth->allow() in the beforeFilter, you need to add an exception for admin.
To do so, in your AppController:
<?php
class AppController {
public $components = array(
'Auth' => array(
'loginAction' => array('controller' => 'users', 'action' => 'login');
'loginRedirect' => array('controller' => 'pages', 'action' => 'home');
'logoutRedirect' => array('controller' => 'users', 'action' => 'login');
'authorize' => array('Controller'),
)
) ;
public beforeFilter() {
parent::beforeFilter() ;
// Allow everything to not logged user except admin pages
if (isset($this->params["admin"])
&& $this->params["admin"]) {
$this->Auth->deny() ;
}
else {
$this->Auth->allow() ;
}
}
public isAuthorized() {
if (isset($this->params["admin"])
&& $this->params["admin"]) {
return $this->Auth->user('group_id') === 1 ;
}
return parent::isAuthorized() ;
}
} ;

Restricting and redirecting other user from admin in cakePHP

I'm getting issue after logging in the site. There are two kinds of users i.e. 'admin','employer'. When I've logged in by employer, I can access the restricted area of Admin. Below is the AppController of the site..
class AppController extends Controller {
public $helpers = array('Form', 'Html', 'Js', 'Time', 'Auth');
// Change template extension to .php instead of .ctp
var $ext = '.php';
public $components = array(
'Session',
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login'
),
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authenticate' => array('Form' => array('fields' => array('username' => 'email'))),
'authorize' => array('Controller')
)
);
public function isAuthorized($user) {
// Admin can access every action
if (isset($user['type']) && $user['type'] === 'admin') {
return true;
}
// Default deny
return false;
}
public function beforeFilter() {
$this->Auth->allow(array('view', 'index','assessment','question'));
}
}
Now here is the controller which has methods for admin.
class TopicsController extends AppController {
public $scaffold = 'admin';
public function beforeFilter() {
if($this->Auth->user('type')!='employer'){
parent::beforeFilter();
$this->Auth->allow(array('view', 'index','moveup'));
} else {
$this->Auth->deny(array('view', 'index','moveup'));
$this->redirect(array('controller' => 'employer' , 'action' => 'index'));
}
}
public function isAuthorized($user) {
return true;
}
public function index() {
$this->set('topics', $this->Topic->children());
}
}
If admin URL is www.example.com/admin/topics , Employer is redirected to www.example.com/admin/employer which is not right URL to be redirected.
Also want to know about public $scaffold = 'admin'; as It's little unclear to me.
Please help me..
Ok.. Found one way to redirect, which made my issue solved for a now.. Still looking for proper answer if anybody has..
I changed code from
$this->redirect(array('controller' => 'employer' , 'action' => 'index'));
to
$this->redirect('employer');
..
EDIT: Thanks Alex, I've used
$this->redirect(array('controller' => 'employer' , 'action' => 'index', 'admin'=>false));
and it's working too..

Checking user role on login using CakePHP?

I want to create an admin panel for my site, for this I've created admin.ctp. In DB table name user contain column role, where role=admin/regular(user).
There is only one login form, and the question is, Is it possible to place a 'check' that if user.role=admin then redirect to the admin/user/dashboard and if user.role=regular then layout=default? my AppController.php contains:
function beforeFilter(){
$this->Auth->allow('index','view','login','home');
$this->set('admin',$this->_isAdmin());
$this->set('logged_in',$this->Auth->loggedIn());
$this->set('current_user',$this->Auth->User());
if ((isset($this->params['prefix']) && ($this->params['prefix'] == 'admin'))) {
$this->layout = 'admin';
}
And usersController.php
function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('*');
if($this->action=='add' || $this->action=='edit'){
$this->Auth->authenticate=$this->User;
}
}
function login(){
if(!($this->Auth->loggedIn())){
if ($this->request->is('post')) {
if ($this->Auth->login()) {
if($user['role'] === 'admin'){
$this->redirect($this->Auth->redirect('admin',array('controller' => 'user','action' => 'admin_dashboard')));
}
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
} else {
$this->Session->setFlash('Your username/password combination was incorrect.',
'alert',array(
'plugin' => 'TwitterBootstrap',
'class' => 'alert-error'
));
$this->set('forget', 'Forgot Your Password');
}
}
}else
{
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
}
}
using cakephp 2.2.3.
thanks in advance!
This is how I would do it (remember to change field('name') accordingly with your group model).
if ($this->Auth->login())
{
this->User->Group->id = $this->Auth->user('group_id');
switch ($this->User->Group->field('name'))
{
case 'admin':
$this->redirect($this->Auth->redirect('admin',array('controller' => 'user','action' => 'admin_dashboard')));
break;
case 'regular':
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
break;
default:
//...
break;
}
}
In AppController set:
$this->Auth->authorize = array('Controller');
And then do the following
public function isAuthorized($user = null)
{
if (isset($this->request->params['admin']))
{
if(!isAdmin)
{
return false;
}
}
return true;
}
CakePHP actually already provides a useful Authentication and Authorization framework that's trivial to enable.
Here's how to authorize based on a role stored in the database, from the CakePHP manual. I also included an example beforeFilter() that changes the login redirect action if the user is an admin:
AppController.php:
public $components = array(
'Auth' => array(
'authorize' => array('Controller'),
'loginRedirect' => array('/'),
));
public function beforeFilter() {
// This allows us to use $user in all controllers.
$this->set('user', $this->Auth->user());
// If the user is an admin, override the loginRedirect
if ('admin' === $this->Auth->user('role')) {
$this->Auth->loginRedirect = array(
'controller' => 'users',
'action' => 'admin_dashboard',
));
}
}
UsersController.php:
public function isAuthorized($user) {
// Ensure the user has a valid role. If not, deny access to all actions:
if ((!isset($user['role'])) || ('' === $user['role'])) return false;
// If we're trying to access the admin view, verify permission:
if ('admin_dashboard' === $this->action)
{
if ('admin' === $user['role']) return true; // User is admin, allow
return false; // User isn't admin, deny
}
return true;
}
There are many ways you can arrange the authorization, so adjust the if/else statements to best suit your needs. The isAuthorized() method is relatively simple, you just need to return true if you want to allow access, or false if you don't.
I actually want to post some code to perhaps shed light on this subject for myself as well.
I have achieved a simple dashboard for each user that extends the /Users/view - my next step is trying to get User-specific access to each set of data
AppController
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
//Configure AuthComponent
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'dashboard');
$this->Auth->allow('display');
}
}
UsersController
public function dashboard() {
$id = $this->Auth->user('id');
$this->set('user', $this->User->read(null, $id));
$group_name = $this->User->Group->field('name', array('id' => $this->Auth->User('group_id')));
$this->redirect = array('controller' => 'users', 'action' => 'dashboard');
}
dashboard.ctp
$this->extend('/Users/view');
<?php public function dashboard() {
$id = $this->Auth->user('id');
$this->set('user', $this->User->read(null, $id));
$group_name = $this->User->Group->field(
'name', array('id' => $this->Auth->User('group_id'))
);
$this->redirect = array('controller' => 'users', 'action' => 'dashboard');
}
?>

Resources