Cakephp 3 authentication - authentication

I'm working with Cakephp3 and I got problem with Auth system.
Here's my code in UsersController:
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');
}
}
In AppController:
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth',[
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
]
]]);
}
in login.ctp:
<?php
echo $this->Form->create();
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->button('log in');
echo $this->Form->end();
?>
and I've created a table called users which has fields: Full texts
id
first_name
last_name
username
password
created
modified
and I have sample user with the Username= hosein , password:123 but when I put in the data that does not work and says invalid username of password.
really why?!

Related

Cakephp 4 logintest

I'm doing the test for my UserController and I'm having trouble with my login test. I'm using cakephp4 with phpunit.
The test I'm doing is this:
public function testLogin(): void
{
$this->enableSecurityToken();
$this->enableCsrfToken();
$this->get('/user/login');
$this->assertResponseOk();
$this->post('/user/login', [
'DNI_CIF' => '22175395Z',
'password' => '$2y$10$ND67aMGqm.qK86MW1wuW9OQLC9vyJQGUn2HnLuSInwrFbXQKBT.V.'
]);
$this->assertResponseCode(302); //Si correcto redirige
// $this->assertSession(1, 'Auth.User.id');
}
My UserController:
public function login()
{
$this->request->allowMethod(['get', 'post']);
$result = $this->Authentication->getResult();
// regardless of POST or GET, redirect if user is logged in
if ($result && $result->isValid()) {
return $this->redirect('/');
}
// display error if user submitted and authentication failed
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->error(__('Alias de usuario o contraseña incorrecta.'));
}
}
My Application:
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$authenticationService = new AuthenticationService([
'unauthenticatedRedirect' => Router::url('/user/login'),
'queryParam' => 'redirect',
]);
// Load identifiers, ensure we check email and password fields
$authenticationService->loadIdentifier('Authentication.Password', [
'resolver' => [
'className' => 'Authentication.Orm',
'userModel' => 'User',
],
'fields' => [
'username' => 'DNI_CIF',
'password' => 'password',
]
]);
// Load the authenticators, you want session first
$authenticationService->loadAuthenticator('Authentication.Session');
// Configure form data check to pick email and password
$authenticationService->loadAuthenticator('Authentication.Form', [
'fields' => [
'username' => 'DNI_CIF',
'password' => 'password',
],
'loginUrl' => Router::url('/user/login'),
]);
return $authenticationService;
}
But I'm having this error:
.......object(Authentication\Authenticator\Result)#826 (3) {
["_status":protected]=>
string(27) "FAILURE_CREDENTIALS_MISSING"
["_data":protected]=>
NULL
["_errors":protected]=>
array(1) {
[0]=>
string(27) "Login credentials not found"
}
}
Can someone tell my what I'm doing wrong?
I tried several combinations like:
'username' => '22175395Z',
'password' => '$2y$10$ND67aMGqm.qK86MW1wuW9OQLC9vyJQGUn2HnLuSInwrFbXQKBT.V.'
or:
'DNI_CIF' => '22175395Z',
'password' => 'prueba'
or
'username' => '22175395Z',
'password' => 'prueba'
but nothing works.
In order to validate against a password stored in the database, the stored password must be hashed, and the submitted password must not be.
A want to add, in case of someone having the same problem, to be careful if you are using a user added in Fixture to login because it's password may not be hashed and login test will not work. I added a user and used it in the login test.

cakephp 3.8.13 add admad/cakephp-jwt-auth

This question is asked many times in the stack overflow but I tried every accepted solution.
I'm new to cake PHP and I was assigned to add JWT in our application. Previously the team used the default cake sessions. In order to integrate, I used admad/cakephp-jwt-auth. So In the AppController
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Recurring');
$this->loadComponent('Auth', [
'storage' => 'Memory',
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'user_name',
'password' => 'password',
],
'contain' => ['Roles']
],
'ADmad/JwtAuth.Jwt' => [
'parameter' => 'token',
'userModel' => 'CbEmployees',
'fields' => [
'username' => 'id'
],
'queryDatasource' => true
]
],
'unauthorizedRedirect' => false,
'checkAuthIn' => 'Controller.initialize'
]);
}
I have to use CbEmployees which is our user model.
Then in my custom controller, I add my login function
public function login()
{
$user = $this->Auth->identify();
if (!$user) {
$data = "Invalid login details";
} else {
$tokenId = base64_encode(32);
$issuedAt = time();
$key = Security::salt();
$data = JWT::encode(
[
'alg' => 'HS256',
'id' => $user['id'],
'sub' => $user['id'],
'iat' => time(),
'exp' => time() + 86400,
],
$key
);
}
$this->ApiResponse([
"data" => $data
]);
}
Then I call this function using postman with body
{
"username": "developer",
"password": "dev2020"
}
I always get the response as Invalid login details. So the suggested solution is to check the password data type and length. The password is varchar(255). Another solution is to check the password in the entity. In the entity I have
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return Security::hash($password, 'sha1', true);
// return (new DefaultPasswordHasher)->hash($password);
}
}
I specifically asked why the team is using Security::hash($password, 'sha1', true); due to migration from cake 2 to cake 3 they have to use the same.
Why I'm getting always Invalid login details? What I'm doing wrong here? I can log in the using the same credentials when I'm using the application.

custom finder not working in CakePHP 3

I'm working on CakePHP 3.3. I want user to login using either email or mobile number along with password.
I have users table with email, mobile, password, etc fields.
According to CakePHP doc, I'm using custom finder auth to login.
Auth component in AppController.php
$this->loadComponent('Auth', [
'loginRedirect' => [
'controller' => 'Dashboard',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'home'
],
'authenticate' => [
'Form' => [
'finder' => 'auth'
]
]
]);
and findAuth() action in UsersTable.php
public function findAuth(Query $query, array $options)
{
$query
->select(['id', 'email', 'mobile', 'password'])
->where(['Users.email' => $options['login']])
->orWhere(['Users.mobile' => $options['login']]);
return $query;
}
and login() action in UsersController.php
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->registerError(__('Invalid Credentials, try again'), ['key' => 'registration']);
}
}
login.ctp view contains
<?php
echo $this->Form->create();
echo $this->Form->input('login');
echo $this->Form->input('password');
echo $this->Form->submit();
echo $this->Form->end();
?>
But this is not working and prints Invalid Credentials, try again
Update 2
Added a blank column username to users table.
login.ctp
<?php
echo $this->Form->create();
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->submit();
echo $this->Form->end();
?>
AppController.php:authComponent
same as above
findAuth()
public function findAuth(Query $query, array $options)
{
$query
->orWhere(['Users.email' => $options['username']])
->orWhere(['Users.mobile' => $options['username']]);
return $query;
}
Now it's working. But why force to use username column even if not needed in application.
You must SELECT all the fields you need to authenticate a user, as described on doc.
public function findAuth(Query $query, array $options)
{
$query
->select(['id', 'email', 'mobile', 'username', 'password'])
->orWhere(['Users.email' => $options['login']])
->orWhere(['Users.mobile' => $options['login']]);
return $query;
}
And be sure $options['login'] is on your form.
Update:
If you are using 'login' as Form input try using:
'authenticate' => [
'Form' => [
'finder' => 'auth',
'fields' => ['username' => 'login', 'password' => 'password']
]
]
fields The fields to use to identify a user by. You can use keys username and password to specify your username and password fields respectively.
My own Query using my App (without fields => [username => login]):
SELECT
Users.id AS `Users__id`,
Users.username AS `Users__username`,
Users.password AS `Users__password`,
Users.role AS `Users__role`,
Users.email AS `Users__email`
FROM
users Users
WHERE
(
Users.email = 'user#example.com'
OR (
Users.username = 'user#example.com'
AND Users.username = 'user#example.com'
)
)
My login is similar, but is using username and email instead of your fields.
Update 2:
The documentation is not so great. So testing I figured that by default using a custom finder the query will be modified by Cake adding the first WHERE this = 'something', then the solution is using orWhere on all the others (findAuth modified).
New Query:
SELECT
Users.id AS `Users__id`,
Users.username AS `Users__username`,
Users.password AS `Users__password`,
Users.role AS `Users__role`,
Users.email AS `Users__email`
FROM
users Users
WHERE
(
Users.email = 'user'
OR Users.username = 'user'
)

cakephp 3.0 Auth & single sign on

I am using cakephp 3.0 and in the login page although I try to enter the right credentials i get invalid username or password message.
In my user table , I have the fields username and password by which i want to authenticate user.
I have tried to follow the cake book documentation for 3.0 except the step where for including password hashing.Also used the table structure similiar to the one in cakephp documentation
Is it because it is accessing the wrong table?I have mentioned the fields in App Controller
Also if i have to implement single sign on ,is there a plugin which could help me out?Please provide links to such tutorials as this is important for my graduate studies project
My model file:
class UsersTable extends Table
{
public function initialize(array $config)
{
$this->table('users');
$this->displayField('User_id');
$this->primaryKey('User_id');
$this->addBehavior('Timestamp');
}
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->notEmpty('id', 'create')
->notEmpty('username','Username is required')
->notEmpty('password','Password is required')
->notEmpty('role');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['username']));
return $rules;
}
}
My UserController file
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Core\App;
use Cake\Event\Event;
class UsersController extends AppController
{
public function view($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
$this->set('user', $user);
$this->set('_serialize', ['user']);
}
public function register()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success('The user basic details has been saved.');
} else {
$this->Flash->error('The user could not be saved. Please, try again.');
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
public function edit($id = null)
{
$user = $this->Users->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success('The user has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The user could not be saved. Please, try again.');
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success('The user has been deleted.');
} else {
$this->Flash->error('The user could not be deleted. Please, try again.');
}
return $this->redirect(['action' => 'index']);
}
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
// Allow users to register and logout.
// You should not add the "login" action to allow list. Doing so would
// cause problems with normal functioning of AuthComponent.
$this->Auth->allow(['register', 'logout']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
$this->set('user',$user);
if ($user) {
$this->Auth->setUser($user);
$this->Flash->error(__('Login successful'));
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}
public function logout()
{
return $this->redirect($this->Auth->logout());
}
public function index()
{
$this->set('users', $this->paginate($this->Users));
$this->set('_serialize', ['users']);
}
}
My AppController file
class AppController extends Controller
{
public function initialize()
{
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
]
]
],
'loginRedirect' => [
'controller' => 'Orders',
'action' => 'view'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'display',
'home'
]
]);
$this->Auth->allow(['display']);
}
public function beforeFilter(Event $event)
{
$this->Auth->allow(['index', 'view', 'display','login']);
}
}
My login page:
<div class="users_form">
<?=$ this->Flash->render('auth') ?>
<?=$ this->Form->create() ?>
<fieldset>
<legend>
<?=_ _( 'Please enter your username and password') ?>
</legend>
<?=$ this->Form->input('username') ?>
<?=$ this->Form->input('password') ?>
</fieldset>
<?=$ this->Form->button(__('Login')); ?>
<?=$ this->Form->button(__('Register')); ?>
<?=$ this->Form->end() ?>
</div>
I figured out what was wrong.
First place I had not included the password hasher method.
On trying to include that ,I added it to the wrong module.It must be added for the Entity class file whereas I was adding it to The UserTable.php.
This was not helping my case at all.I followed the manual to the T .
After adding the password Hasher module I added a new user.
Also it is true that it works only if the password length is varchar(255)
Therefore the user along with hashed password was created.
I was then able to login

Login function of Auth not working with cakePhp-2.6

I have set up my website so only add and login are only accessible before the user log in. And when he log in, he is redirected to the home page.
But when the user tries to log in, the login page refreshes and it shows this message "Username or password is incorrect" which is from the action login of my controller.
I verified and it's "$this->Auth->login()" which is not working.
In my database, i used these fields for the user table: id, password, nom, prenom, username.
Here is the login function code from my controller UsersController:
public function login()
{
if ($this->request->is('post'))
{
if ($this->Auth->login())
{
return $this->redirect($this->Auth->redirectUrl());
}
else
{
$this->Session->setFlash(__('Username or password is incorrect'));
}
}
}
Here is the login view code:
<?php
echo $this->Session->flash('auth');
echo $this->Form->create('User');
echo $this->Form->input('username', array('label' => 'Votre pseudo: '));
echo $this->Form->input('password', array('label' => 'Votre mot de passe: '));
echo $this->Form->end('Se connecter');
?>
Here is User model code:
<?php
App::uses('AppModel', 'Model');
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');
class User extends AppModel
{
public $hasMany = array('Compte','ComptesUtilisateur');
public function beforeSave($options = array()) {
Security::setHash('md5');
if(isset($this->data[$this->alias]['password']))
{
$passwordHasher= new SimplePasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash($this->data[$this->alias]['password']);
}
return true;
}
}
?>
And here AppController.php code:
class AppController extends Controller {
var $components = array(
'Auth' => array(
'authError' => "Etes-vous sûr(e) d'avoir l'autorisation pour y accéder?",
'loginError' => "Votre pseudo ou votre mot de passe est incorrect",
'loginAction' => array(
'controller' => 'users',
'action' => 'login'
),
'loginRedirect' => array('controller' => 'pages', 'action' => 'home'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'username',
'password' => 'password'
),
'passwordhasher' => array(
'className' => 'Simple',
'hashType' => 'md5'
)
)
)
),
'Session'
);
public function beforeFilter()
{
$this->Auth->allow('login');
}
public function beforeRender()
{
$this->set('auth', $this->Auth->loggedIn());
}
}
I searched the solution on forums but i found nothing.
Any indication?
Thanks,
Louberlu.