After migrating a fully functional Cake 1.3 application to the recently released 2.0 version Authentication has ceased to work.
I've changed the calling of the AuthComponent and the structure of the login action according to the updated 2.0 manual, to no avail. The strange thing is the user is actually validated by $this->Auth->login() as it reaches the part of the login function where the user is redirect to the url set by $this->Auth->redirect(). After that redirect however, $this->Auth->user() returns empty (as well as AuthComponent::user()) and the user isn't logged in by the Auth component.
Cake doesn't throw any error during the process, the flash messages for 'auth' remain empty.
Users are stored in a simple database table containing id, username, email, password and timestamp columns. The passwords are hashed and I've added some users using the new Cake 2.0 methods.
This is the code of AppController.php:
<?php
class AppController extends Controller {
public $helpers = array('Session', 'Html', 'Time', 'Form', 'Text');
public $components = array('Session', 'RequestHandler', 'Auth');
public function beforeFilter() {
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'maps', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => 'maps', 'action' => 'index');
}
}
?>
UserController.php:
<?php
class UsersController extends AppController {
public $name = 'Users';
function beforeFilter() {
parent::beforeFilter();
}
function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
}
}
function logout() {
$this->redirect($this->Auth->logout());
}
}
?>
User.php model. I've disabled form validation for the time being after I solve this problem:
<?php
class User extends AppModel {
public $name = 'User';
}
?>
The login view:
<?php
echo $this->Form->create('User');
echo $this->Form->input('username', array('label' => 'Username', 'before' => '<p class="input" id="username">', 'after' => '</p>', 'between' => '<br />', 'div' => false));
echo $this->Form->input('password', array('label' => 'Password', 'before' => '<p class="input" id="password">', 'after' => '</p>', 'between' => '<br />', 'div' => false));
echo $this->Form->end('Login');
?>
I also tried to setting some of the Auth features in the $components variable in the AppController, which didn't work as well:
public $components = array(
'Auth'=> array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login',
),
'loginRedirect' => array(
'controller' => 'maps',
'action' => 'index',
),
'authenticate' => array(
'Form' => array(
'fields' => array('username', 'password')
)
)
)
);
What's causing the problem here? Routing maybe? I've commented out all routes except:
require CAKE . 'Config' . DS . 'routes.php';
UPDATE:
After adding some debug statements in the login method in the UsersController I now know $this->Auth->user() is actually populated with the correct user after the call to $this->Auth->login(). After the redirect to another controller the login session is lost completely, however. So I still don't know what's going wrong here.
UPDATE 2
I've restarted the process of migrating by taking my working 1.3 application and running the migration console script on it like I did the last time.
This time I noticed the script stopped because of two errors relating to custom components. Component classes should extend Component now, instead of the 1.3 default: Object.
After fixing these component errors I ran the migration script again (something I neglected to do during the first migration attempt) and implemented the new AuthCompenent call. So far everything seems to be working correctly. Not sure what's different now and what went wrong the first time, as Cake didn't output any error messages.
UPDATE 3
It's getting weirder. I thought I solved it, but after transferring my code to another development machine Auth suddenly stops working. It's working on my main setup, but while testing on another it fails again following the same scenario. I've cleared the cache to be sure, but it still isn't working. Cake doesn't generate any error output.
UPDATE 4
It appears to be a Session problem on my machine. I've just set the Session to be stored in a cookie and suddenly Auth starts working again. Not sure why the default Session isn't working and I don't know where to start debugging in that case.
Only cookie sessions appear to work, defining a database session has the same result as a regular session; Auth stops working.
Try it with use_trans_sid enabled in /Config/core.php:
Configure::write('Session', array(
//'defaults' => 'php'
'defaults' => 'cake',
'cookie' => 'CAKEPHP2',
'ini' => array('session.use_trans_sid' => true)
));
Did you try also to configure the Authentication handler ?
public $components = array(
'Auth'=> array(
'authenticate' => array('Form')
)
);
Related
My auth component has been working fine for the past year. I was logged into my site about two hours ago and made a single minor change. I got off for those two hours and since I've returned about a half hour ago, I have been unable to log into my site. The error message says the username/password combination is incorrect. I thought somehow the values got changed in my database or that my browser had autosaved an old password so just to be sure I updated the password in my database with it's appropriate md5 hashed value and I tried it again in my browser. It still did not work.
I emptied my cache (which is something I do quite often any way) because I was suggested to do so from this post but this too did not work (nor did it help the poster of that question). That person's solution of having added something to the view file that broke the database connection does not apply to me because I did not change any of the view files. Nor have I changed the user model or app controller. The ONLY thing I changed during the time I was on earlier was that I edited the UsersController online() action. I have since changed it back. In fact, I went into my site backup utility and restored all controller and model files to their latest backup which was 2 days ago when everything was working. Still no affect.
I cannot log into any of the accounts I have registered. I even unhashed one of the passwords in the database and tried logging in with that account but that didn't work either.
AppController
//I HAVE NOT CHANGED THIS IN SEVERAL MONTHS
public $helpers = array('Form', 'Html', 'Custom', 'Time', 'Js', 'Cache');
public $components = array('CustomPage', 'Session', 'CustomUser',
'Auth' => array(
'autoRedirect' => false,
'loginAction' => array('controller' => 'users', 'action' => 'login', 'prefix' => false, 'admin' => false, 'moderate' => false),
'loginRedirect' => array('prefix' => false, 'admin' => false, 'moderate' => false, 'controller' => 'account', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'index', 'prefix' => false, 'admin' => false, 'moderate' => false),
'authError' => "You can't access that page",
'authorize' => array('Controller')
)
); // components
public function isAuthorized($user) {
return true;
}
UsersController
// DID NOT CHANGE FOLLOWING ACTION
public function login() {
if ($this->Session->read('Auth.User')) {
$this->Session->setFlash('You are already logged in');
$this->redirect(array('controller' => 'account', 'action' => 'index'));
}
$this->layout = "simple";
$this->set('title_for_layout', 'Login');
if ($this->request->is('post')) {
$this->User->UsersOnline->deleteAll(array('UsersOnline.session' => $this->viewVars['session_session']), false);
if ($this->Auth->login()) { // check user is logged in
$this->User->id = $this->Auth->user('id');
$this->User->saveField('last_login', date(Configure::read('Site.date_format'))); // save login time
$this->redirect($this->Auth->redirect()); // redirect to default place
} else {
$this->Session->setFlash('Your username/password combination was incorrect');
}
}
} // end login
// THE FOLLOWING ACTION WAS THE ONLY THING
// THAT WAS CHANGED BUT IT IS NOW BACK TO ORIGINAL VERSION
public function online() {
$page_id = $this->viewVars['page_id'];
$link = $this->viewVars['link'];
// CONTAIN
$this->User->UsersOnline->contain(array(
'User' => array(
'fields' => array(
'User.username', 'User.online'
),
'Avatar' => array(
'fields' => array(
'Avatar.file'
)
)
)
));
if($page_id){
$this->set('users', $this->paginate($this->User->UsersOnline, array('UsersOnline.page_id' => $page_id)));
$this->set('title_for_layout', 'Fans Online');
}
else{
$this->set('title_for_layout', 'Users Online');
$this->set('users', $this->paginate($this->User->UsersOnline));
$this->layout = "default";
}
} // end online action
My user model uses the standard "username" and "password" columns to authenticate a user.
I've added the following code to my UserController login() action and the correct result is printed...
$password = md5($this->request->data['User']['password']);
print_r(
$this->User->find('first',
array(
'User.username' => $this->request->data['User']['username'],
'User.password' => $password
)
)
);
Again, I have restored ALL controller and model files to their state from 2 days ago so I really have no idea what could be causing this.
Edit 1: And now just to be safe, I reverted all my view files back to their latest backup versions from this weekend. This did not fix the issue.
Edit 2: If I debug $this->Auth->login, the result is empty. Why would this be empty all of a sudden if nothing has changed?
Edit 3: My UsersController register() action properly creates a new user and automatically logs that user in.
UsersController
public function register() {
if($this->Session->read('Auth.User')) {
$this->Session->setFlash('You are already registered');
$this->redirect(array('controller' => 'account', 'action' => 'index'));
}
$this->layout = "simple";
$this->set('title_for_layout', 'Register');
if ($this->request->is('post')) {
$this->User->create();
if ($this->User->save($this->request->data)) {
$id = $this->User->id;
$this->request->data['User'] = array_merge($this->request->data['User'], array('id' => $id));
if($this->Auth->login($this->request->data['User'])){
$this->Session->setFlash(__('Your account has successfully been created and you have logged in'));
$this->redirect(array('controller' => 'account', 'action' => 'index'));
} // end if account created and successful log in
else{
$this->Session->setFlash(__('Your account has successfully been created but you cannot log in'));
} // end else if account created but not logged in
} else {
$this->Session->setFlash(__('Your account could not be created. Please, try again.'));
} // end else if account cannot be created
} // end if method is post
} // end register
Well, I never figured out what the INITIAL issue was but now I found out that reverting all of my changed controller, model, AND view files seem to solve the issue. It still bothers me that I don't know what the initial issue was.
However, I DID discover that after I updated all my passwords in my database to their corresponding md5 hash, that was giving me the ongoing issue. I guess Cake doesn't use md5 which I thought so the passwords weren't being matched properly. So even after reverting all my changed files, the passwords all became incorrect.
If I ever figure out what the original issue was I will update.
It may help to remove all files from tmp/cache and tmp/models
I had the same problem.It was working fine but suddenly after some changes in code that was nothing to do with the login part the login function was not working and deleting the changes I made didnt help and when I searched and find out that you have the same problem and you didnt find what the problem is I figured out that it must be some thing very simple as it didnt give me any error and I suddenly found that when I was editing the user controller file I accidently wrote the ' char in the begining of the file and I removed it and the problem is solved!
I've created a plugin called 'IssueTracker', which is located in app/Plugin/IssueTracker. I've created a Controller called Tickets and it is accessible at www.example.com/issue_tracker/tickets/. But, only for logged in users with the rank 'Admin'.
That wasn't exactly what I was hoping for, so I added in my Plugin/IssueTracker/Controller/TicketsController.php the following:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index');
}
I hoped that with this piece of code (which I'm using in several other controllers in my app/Controller/ that it would inherit from my AppController.php file. The TicketsController.php file extends the IssueTrackerAppController (like this):
class TicketsController extends IssueTrackerAppController {
//functions goes in here
}
And in my Plugin/Controller folder I've created the file IssueTrackerAppController which extends the AppController.
In my AppController.php file I've allready defined that 'index' and 'view' are public actions. But, for some reason, it doesn't work in my plugin.
Is there something that I'm overseeing? When I access www.example.com/issue_tracker/tickets as a not logged in user (Guest), it tells me that I need to login. If I'm logged in as a user, but not as an Admin, the Auth component won't allow me in and presents the login form.
There should be a way to get Auth working in a plugin, right?
EDIT
Below is the AppController.php snippet where I've configured Auth:
public $components = array(
'Auth' => array(
'loginAction' => array('controller' => 'users', 'action' => 'login', 'plugin' => false),
'loginRedirect' => array('plugin' => false, 'controller' => 'ervaringen', 'action' => 'add'),
'logoutRedirect' => array('plugin' => false, 'controller' => 'ervaringen', 'action' => 'index'),
'authorize' => array('controller'),
'flash' => array(
'element' => 'error',
'key' => 'auth',
'params' => array(
'heading' => 'Waarschuwing!')
),
'authError' => 'Je moet inloggen om deze inhoud te bekijken.',
),
'Session',
'DebugKit.Toolbar'
);
Mystery solved.
After rescanning all the code in the plugin, I noticed that one of my coworkers on the project used $variable = $this->requestAction(link/here/with/id/etc);, which leads towards a controller function. That particular function wasn't allowed in any way by the beforeFilter(), causing a 'function denied' bij the Auth system.
I've added this particular function in $this->Auth->allow('function'); in the beforeFilter() of the plugin and now it is working.
I am having some issues with the CakePHP Auth login. For some reason, instead of the site going to the path i have laid out for it, it looks at the form and goes right to the login function.
To explain, here is my code,
Router File :
Router::connect('/clientlogin', array('controller' => 'pages', 'action' => 'UsersLogin'));
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Pages Controller - UsersLogin Function :
public function UsersLogin() {
$this->render('/Pages/LoginForm');
} //End of UsersLogin function
Users Controller - login Function :
public function login() {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash('Invalid Username Or Password, Please Try Again', 'default', array(), 'bad');
$this->redirect($this->Auth->redirect());
}
} //End of Login function
LoginForm.cpt Code :
echo $this->Session->flash('auth');
echo $this->Form->create('User', array('url'=>'/login', 'id' => 'LoginForm'));
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->submit('Login', array('class' => 'Button'));
echo $this->Form->end();
My main menu in my site has a 'login' button that points to '/clientlogin', which loads the form for my users to login with. However, when the session information expires, the areas of the site which require login to access them push me over to re-login.
But CakePHP is not going to /clientlogin its going to /login - which is not the form but the login controller. Also it dose not matter what I change it to but where ever I point my form is where Cake whats to go. For example, I changed the form to point to /mylogintest or /loginuser and Cake went to these paths instead.
So my main question is, when Cake needs to re auth the session information, how do I make sure it points to my clientform path and not the path laid out in my form.
If I have not been clear or, I have not posted something needed, then please ask me and I will try and fix it.
Many Thanks for any help given
Glenn.
You can change the default login action by passing extra keys into the components. See the code below :
// Pass settings in $components array
public $components = array(
'Auth' => array(
'loginAction' => array(
'controller' => 'pages',
'action' => 'UsersLogin'
)
)
);
I am not sure why you need to create separate action to contain the login form. Usually I'll have the form inside the login action and check the request using $this->request->is('post'). See the Cookbook for more information http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
I have a simple form in a a view and I am trying to access the $this=>passedArgs but it is coming back empty.
I am actualy trying to use the cakeDC search plugin which uses the $this=>passedArgs. It must be something simple I have not done to get the results from the form submit.
find view
<?php
echo $this->Form->create('Member', array(
'url' => array_merge(array('action' => 'find'), $this->params['pass'])
));
echo $this->Form->input('name', array('div' => false));
echo $this->Form->submit(__('Search'), array('div' => false));
echo $this->Form->end();
?>
Controller
public function find() {
debug($this->passedArgs);
exit;
}
I have tried $this->request->params
array(
'plugin' => null,
'controller' => 'members',
'action' => 'find',
'named' => array(),
'pass' => array(),
'isAjax' => false
)
I have add method get to the form.
This question has been asked before but their solution of having lower cases in the public $uses = array('order', 'product'); when it should be public $uses = array('Order', 'Product'); did not work.
Cakephp version 2.3.5
Thanks for any help
Update:
I have set my form to method get and this is the url:
http://localhost/loyalty/members/find?name=searchtext
I have removed the plugin and I still do not get anything $this->passedArgs, but I now get data for $this->request->data['name']. Once I put public $components = array('Search.Prg'); I get noting again for $this->request->data['name'].
I have tried again $this->Prg->parsedParams() with the Search plugin and I just get array()
The documentation is pretty clear on that.
You cannot just debug something that has not been set yet.
So including the plugin itself (and its component) is not enough.
From the readme/documenation:
public function find() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->ModelName->parseCriteria($this->passedArgs);
$this->set('...', $this->paginate());
}
Note the commonProcess() call which then only makes passedArgs contain what you need.
I have done admin routing for my admin panel. Right now the url is localhost/app/admin.
Now I have 2 Tables Admins and Users.
I have created an url for the login localhost/app/admin/admins/login.
The page prompts for a username and a password.
But the Problem is when create component in appcontroller with loginredirect it is redirected to localhost/app/admin/users/login.I don't know why. I even tried changing the loginredirect path but it's nothing worked.
This is my appcontroller.php :
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'admins', 'action' => 'add'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home')
)
);
public function beforeFilter() {
$this->Auth->allow('index', 'view');
}
Even if I delete the user table, it redirects to the users login.
It sounds like your Auth component isn't working. instead of adding the auth redirects into the components variable, put them in your beforeFilter(). Your appController should be:
public $components = array('Auth','Session');
public function beforeFilter()
{
$this->Auth->loginRedirect = array('action' => 'add', 'controller' => 'admins');
$this->Auth->logoutRedirect = array('controller' => 'pages', 'action' => 'display', 'home');
$this->Auth->authError = 'You are not allowed to see that.';
}
Are you logging in successfully? if so, check routes.php to make sure you're routing things correctly. this could be tested by trying to navigat to example.com/admins/add manually.