CakePHP 1.3: getting authError message on successful login - cakephp

I'm trying to implement a login feature where a user can use his username or email address. I've worked out the login with both, but when the user logs in successfully with his email address, the authError still flashes (user is logged in). I've put a comment "HERE" down in the login action, and I'm not sure what happens after that with the redirect.
Here are the relevant bits of my code:
App Controoler:
public $components = array(
'Auth' => array(
'authorize' => 'controller',
'loginRedirect' => array(
'controller' => 'users',
'action' => 'welcome_page'
),
'loginError' => 'Invalid user name/password',
'authError' => 'You don\'t have permission'
),
'Session',
);
User Controller:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add');
}
public function login() {
// At this point, the Auth Component is unable to log in user, so check with email.
if (!empty($this->data) &&
!empty($this->Auth->data['User']['username']) &&
!empty($this->Auth->data['User']['password'])) {
// Look for user with email address using the entered username
$user = $this->User->find('first', array(
'conditions' => array(
'User.email' => $this->Auth->data['User']['username'],
'User.password' => $this->Auth->data['User']['password']
),
'recursive' => -1
));
// Check if a matching user is found and that if login was succesfull
if (!empty($user) && $this->Auth->login($user)) {
if ($this->Auth->autoRedirect) {
// NOTE: user trying to log in with email reaches HERE
$this->redirect($this->Auth->redirect()); // this is the default authentication redirect defined in App Controller
}
} else {
$this->Session->setFlash($this->Auth->loginError, $this->Auth->flashElement, array(), 'auth');
}
}
}

I edited your original post to delete the messages from the session variables.
<?php
$this->Session->delete('Message.flash');
$this->Session->delete('Message.auth');
?>
Hope this helps!
-Andrew

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.

Cake php auth login response

public function login() {
//if already logged-in, redirect
if($this->Session->check('Auth.User')){
$this->redirect(array('controller'=>'pages','action' => 'index'));
}
// if we get the post information, try to authenticate
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$status = $this->Auth->user['status'];
if($status != 0){
$this->Session->setFlash(__('Welcome, '. $this->Auth->user('username')));
$this->redirect(array('controller'=>'pages','action' => 'index'));
}else{
$this->Session->setFlash(__('The user is not active'));
}
} else {
$this->Session->setFlash(__('Invalid username or password'));
}
}
}
why I use this function for login . At first time I login with status 1 the system report user is not active but I login at second time with status 1 ok .
change
$status = $this->Auth->user['status'];
to
$status = $this->Auth->user('status');
user is a function in AuthComponent
If you want to only log users with status = 1, you can also try to use the scope
example:
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'scope' => array('status' => '1')
),
)
),
);

CakePHP: Get loggedin user data

What I did
I used this part of the Cookbook to create my authentication: Link
After i was finished, i changed the fields to email and password (in AppController.php):
public function beforeFilter() {
$this->Auth->allow('index');
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
}
What happened
The login form always said that my password/email combination was not correct.
After a while searching and trying stuff, i added "$this->request->data" to the Auth->login() parameter in the login() function of the UsersController:
public function login(){
$this->layout = 'login';
if ($this->request->is('post')){
if ($this->Auth->login($this->request->data)){
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Ongeldig email adres of wachtwoord. Probeer het AUB opnieuw'));
}
}
}
This worked, but now i can't use "$user['id']" to get the loggedin users id. It says that it doesn't know the $user variable.
What I expected to happen
In the first place, it should have logged the user in without me adding the parameter. And second, it should have printed the loggedin user's id.
I hope someone can help me with the problem.
Thanks in advance!
fields is now in the authenticate array:
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email', ...)
)
)
see
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#configuring-authentication-handlers
either with
$this->Auth->authenticate = ...
or
public $components = array(
'Auth' => array(
'authenticate' => ...
)
);
but, as PHP freelancer stated, this is well documented.
what cookbook version did you use? the 2.x one?

CakePHP $this->Auth->login() not working

The web app is working great except for auth manual calls. I've been struggling with this for days. In my sample code I have temporarily rewritten the cookie to narrow down the cause. Here is my app controller snip:
App::import('Sanitize');
//uses('sanitize');
class AppController extends Controller {
var $components = array('Clean','Acl', 'Auth', 'Session', 'RequestHandler', 'Cookie', /* 'DebugKit.Toolbar' */);
var $helpers = array('uiNav','Flash','Html', 'Form', 'Session','Javascript','Ajax','Js' => array('Jquery'), 'Time','Js');
function beforeFilter() {
//Configure AuthComponent
$this->Auth->authorize = 'actions';
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'view');
$this->Auth->actionPath = 'controllers/';
$this->Auth->autoRedirect = false;
$this->Auth->allowedActions = array('display');
if(!$this->Auth->user()){
//$cookie = $this->Cookie->read('Auth.User');
$cookie = array('username' => 'chris22', 'password' => 'stuff');
if (!is_null($cookie)) {
$this->set('checking_cookie',$cookie);
if ($this->Auth->login($cookie)) {
$this->set('cookie_message','cookie validates!');
// Clear auth message, just in case we use it.
$this->Session->delete('Message.auth');
/* $this->redirect($this->Auth->redirect()); */
}
}
}
}
}
As you can see I'm just plugging the user name and password into $this->Auth->login and it's not working!!
I don't know if my user controller is relevent, but here is the login function for that too:
function login() {
if ($this->Auth->user()) {
if (!empty($this->data) && $this->data['User']['remember_me'] && isset($this->data['User']['password'])) {
$cookie = array();
$cookie['username'] = $this->data['User']['username'];
$cookie['password'] = $this->data['User']['password'];
$this->Cookie->write('Auth.User', $cookie, true, '+1 month');
//unset($this->data['User']['remember_me']);
$this->set('cookie-00', 'setting cookie.');
}else{ $this->set('cookie_message', 'not setting cookie.');}
$this->redirect($this->Auth->redirect());
}
}
Thanks!
EDIT - 1 - I think I know why this is not working for you.
Reason 1: $this->Auth->login takes data in the form of
array(
'User'=>array(
'username'=>'myusername',
'password'=>'mypassword'
)
)
Reason 2: $this->Auth->login does NOT hash the password.
You must send the password exactly as it appears in the database.
EVERYTHING BELOW THIS LINE IS POSSIBLE BUT NOT LIKELY IN THIS CASE:
Are you sure that when you originally created the username and password, the hashes were setup?
To check that your hashes match look at your users table with phpmyadmin or mysql workbench and find the password field for the user chris22
Compare that entry to your current hashing. To check your current hash, put the code below somewhere in a controller function (index) and navigate there.
debug(Security::hash('stuff'));
exit;
I hope this helps!
Make sure the fields are correctly assigned in the Auth component.
if you use different field names than username & password to connect, you must declare them in your controller like this way :
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email', 'password' => 'mot_de_passe')
)
)
)

Resources