cakePHP auth component not working - cakephp

I have an issue with cake's auth that I simply can't seem to get past (i've been debugging and trying different tutorials for the last two days). As far as I can see it should be very simple, the problem is whenever i try to login, it just refreshes the login page. I cannot for the life of me figure out why! My only conclusion is that there must be something (basic) which tutorials take for granted that I have missed.
Here are a couple of snippets:
users_controller.php
class UsersController extends AppController {
var $name = 'Users';
function beforeFiler() {
parent::beforeFilter();
}
function login() {
}
function logout() {
$this->Session->setFlash('You have successfully logged out.');
$this->redirect($this->Auth->logout());
}
}
app_controller.php
class AppController extends Controller {
var $helpers = array('Html','Form','Javascript');
var $components = array('Auth');
function beforeFilter() {
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'contents', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => 'contents', 'action' => 'view');
$this->Auth->loginError = 'Something went wrong';
$this->Auth->allow('register', 'view');
$this->Auth->authorize = 'controller';
$this->set('loggedIn', $this->Auth->user('id'));
}
function isAuthorized() {
return true;
}
}
login.ctp
<div class="midCol short">
<h3>Login</h3>
<div class="loginBox">
<?php e($form->create('User', array('controller'=>'users','action'=>'login')));?>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
e($this->Form->end(array('label'=>'Login', 'class'=>'loginButton button png')));?>
</div>
</div>
Any help would be greatly appreciated, this has me tearing my hair out!

Just for documentation as I had difficulties finding an answer for CakePHP 2.x on the web. This stuff needs to be "correct" in order to use Form authentication:
The config needs to be right, e.g. in your UsersController (the fields config is really only required when names differ in the DB):
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'username',
'password' => 'password'
),
)
)
)
);
You have to use the Form Helper: Form->create adds a hidden input field ("post"), and the names of the input fields generated by Form->input() follow a convention that the Auth component expects.
User->login must not pass custom data to Auth->login(). The Auth component will take the auth data from the form (= request).

Thanks for the advice, but I ended up scrapping it and building again from scratch. Not exactly sure why it was originally breaking, probably not calling inbuilt functions with American English!

The Auth component will redirect to the page before you logged in. If that page was the login page that's where it'll redirect to.
When you're testing, it's likely that you're refreshing the login page, so on successful login that's where you're redirected to. You can check this by trying to perform an Auth protected action after logging in.
This gives me a lot of headaches as well - I think the current functionality of the component is a little clumsy in that respect.

I had the exact same problem and found that I had to restart mySQL service. Once it was restarted I stopped getting the login page being redirected. Hope that helps.

Gonna throw something in here. I was having an almost unresolveable problem with cakephp authentication. Ended up doing some debugging around it and found that during my database prep I had created a field for the password which was perfectly able to store normal size passwords... but.... when you start applying password hashing you need a lot more. My code was fine, but I had to add a bunch more space into the VARCHAR field for the password before I could log in. If you're having a problem with authentication - make sure your password field is adequately sized and not getting truncated like mine was. Took me a whole day to find that. DOH!

Correct me if i am wrong but must there not be code for redirection or something inside the function of login
function login() {
}
should it not be something like
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}

Related

CakePHP Auth not re-logging in to the right path

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

Cakephp Auth Component - Home page redirect loop

I want to have a login form in my home page, the registered users should be redirected to users/index
with the below code, my home page is going to redirect loop
can anyone tell me where is the issue ??
Note:- infact it is perfectly working if i change the line to
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
App Controller
public function beforeFilter(){
$this->Auth->autoRedirect = false;
$this->Auth->loginAction = array('controller' => './', 'action' => 'index');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => './', 'action' => './');
$this->Auth->authorize = 'controller';
$this->Auth->authError= 'You need permissions to access this page';
$this->Auth->allow('index');
$this->set('Auth',$this->Auth);
}
UsersController
public function login(){
$id = $this->Auth->user('id');
if(empty($id)){
if($this->request->is('post')){
if($this->Auth->login()){
$this->redirect($this->Auth->redirect());
}else{
$this->Session->setFlash('Invalid Username or password');
}
}
}else{
$this->redirect(array('action'=>'index'));
}
}
Thanks for the help...
You pretty much answered your own question here:
Note:- infact it is perfectly working if i change the line to
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
Indeed that would work and that is what it should look like. Right now, you're telling the auth component your loginAction (the action which holds your login logic) is the index action of the ./ controller (which doesn't even exist). I'm assuming you're confusing it with the loginRedirect variable, which is for setting the page to go to after successful authentication.
If you only want Registered Users to Access Your Site you could have something like this... at least, this is how I implement something similar in my site...
In your app_controller file add the following to the beginning of your beforeFilter() function
function beforeFilter(){
//Check if user was able to log in thru Auth using your form in the homepage
if($this->isLoggedIn() == TRUE){
$this->layout = 'default'
}else{
// You can created this layout with a login form and
// whatever else you need except <?php echo $content_for_layout; ?>
// Any registered user will be allowed to login using the form
// and continue on to your site using the default layout
// But it guarantees no one else can see your default site
$this->layout = "unregistered_user"
}
}
On your App_controller.php you can create this function
function isLoggedIn(){
// You can also use $this->Auth->user directly in your App's beforeFilter()
// But I just like to have functions so I can reuse
if($this->Auth->user()){
$loggedin= TRUE;
}else{
$loggedin= FALSE;
}
return $loggedin;
}
I have something similar of my site but is only used when in maintenance mode. I am still developing my site. The only problem I've seen with this way, which I have not yet have time/need to look at, is that my errors are not sent to the layout I want. Supposed a user types in http://www.mydomain.com/inexistentpage then cake transfers them to my default layout. It might be easy to fix, but I havent got time to do that yet.
NOTE: I quickly did this off the top of my head and because of it, this code is untested. However, if you have any issues please let me know and I will test it and post back.
using $this->requestAction(anotherController/action); in the view might call to another controller->action. you must ensure that the another controller->action has the right permissions. or you'll get redirect loop.
solve it by adding $this->auth->allow('action name'); to the another controller page in the beforeFilter() callback.

Cakephp User management plugin implementation

I had downloaded the plugin from link
https://github.com/CakeDC/users
followed the steps given in the page. I have created the tables 'users' and 'details'. I have also registered the user and verfied the user, but while accessing the link www.mydomain/users/users/login this page is getting redirected to www.mydomain/users/login
which shows missing controller. I am new to cake and for me it is difficult to debug. I would be thank if some one help me.
Thank you for the response.
Yes, I have added the code given in the "cake\libs\controller\app_controller.php" file. In order to test this I have freshly downloaded the core files and setup the files in my local system. I have placed the plugins 'utils', 'search' and 'users' to my app/plugins folder and created the tables.
Now also I am able to register the user but not able to see the login page. ie. "while accessing the link www.mydomain/users/users/login this page is getting redirected to www.mydomain/users/login which shows missing controller".
Please let me know if I am missing anything or I am wrong.
Thank you.
This looks like a problem in the login redirection.
Did you add the beforeFilter() configuration to your app_controller?
if not you may need to add it.
Here is an example of how your app_controller should look like:
<?php
class AppController extends Controller {
var $components = array('RequestHandler', 'Session', 'Auth');
function beforeFilter(){
$this->Auth->fields = array('username' => 'email', 'password' => 'passwd');
$this->Auth->loginAction = array('plugin' => 'users', 'controller' => 'users', 'action' => 'login', 'admin' => false);
$this->Auth->loginRedirect = '/';
$this->Auth->logoutRedirect = '/';
$this->Auth->authError = __('Sorry, but you need to login to access this location.', true);
$this->Auth->loginError = __('Invalid e-mail / password combination. Please try again', true);
$this->Auth->autoRedirect = false;
$this->Auth->userModel = 'Users.User';
$this->Auth->userScope = array('User.active' => 1);
}
}
?>
Remember that the $this->Auth->loginAction MOST contain the 'plugin'=>'users', without it it will go to www.mydomain/users/login instead of www.mydomain/users/users/login

CakePHP Logout issues

I know this must be something really stupid, but I am having issues with logging out. I can still see the full user Auth variable after calling Auth->logout(). In my users controller I have the standard:
function login()
{
}
function logout()
{
$this->redirect($this->Auth->logout());
}
But when I call logout, in my view I can still print the User by doing this:
$auth = $this->Session->read('Auth.User');
print "<pre>";
print_r($auth);
print "</pre>";
Am I missing something basic here? Thanks!
mine:
function logout() {
$this->Session->destroy();
$this->redirect($this->Auth->logout());
}
you have not allowed the use of the logout function, and the user is redirected instead of logged out.
in your controller containing logout the function, add this in your before filter:
$this->Auth->allow('logout');
In your app controller you must define a loginAction, in case of a not authorized entry, the view is redirected to that URL
'Auth' => array(
'loginRedirect' => array('controller' => 'products', 'action' => 'all'),
'logoutRedirect' => array('controller' => 'products', 'action' => 'index'),
'loginAction' => array('controller'=>'admins', 'action'=>'login'),
)
You'll find that if you just create a beforeFilter() function in UserController with that one line, you'll break the authorization on the Users model. That is, any user will be able to do users/add, users/edit, etc. To fix this, make sure you call AppController's beforeFilter. The complete beforeFilter() function looks like this:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('logout');
}
If CakePHP is using PHP sessions and not rolling their own, you could just clear out the session on logout via session_destroy();. Sorry I have no CakePHP experience, so I'm just going off of an assumption.
what cake version do you have? I think you have to manually clear session in Cake 1.2. In newer Cake, if the logout function is called, it would clear out Auth.User; I'm sure on that.
I can't see a reason why this shoudn't work as I use exactly the same code...
did you confirm that the method is actually called? a simple "die('xyz')" etc before the Auth logout part can confirm that your action code is triggered.

admin auth check not working

for my client's website I have an admin section- only thing is my admin routing doesn't seem to be password protected. I added the admin protection with a tutorial on how to set up a user system, and have placed the following code in app_controller.php:
function beforeFilter() {
// if an admin route is requested and not logged in
$user = $this->Session->read('User');
if(isset($this->params['admin']) && $this->params['admin'] && is_null($user)) {
// set Flash and redirect to login page
$this->Session->setFlash('You need to be logged in for that action.','default',array('class'=>'flash_bad'));
$this->redirect(array('controller'=>'users','action'=>'login','admin'=>FALSE));
}
}
& in my app/config/routes.php I have this:
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/admin/logout', array('controller' => 'users', 'action' => 'logout'));
which I'm pretty sure is missing something for the protection.
I can still access other admin areas without logging in though, i.e. theowlhouse.com.au/admin/bookings.
What am I doing wrong? The admin page for the users model is the only protected one.
Thanks :)
It looks like you're confusing prefix routing with using the auth component. Note that prefix routing was called 'admin routing' prior to version 1.3.
You don't need to use admin routing to use the auth component. Let's start with just getting the auth component set up. In your app controller, make sure you have it included in your components array:
var $components = array('Auth');
Once you've done that, users will be directed to a login page unless they are logged in. To allow anonymous users to access an action, you make a called to $this->Auth->allow('action name'); So, for example, say you want to allow unauthenticated users to use the index() and view() actions in your items controller, but not add() or edit(). In your items_controller.php, you would set up the beforeFilter() to make a call:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array(
'index',
'view'
));
}

Resources