Check user when email and password are in separate tables. Cakephp
Form accepts by email and pw
<?= $this->Form->create() ?>
<?= $this->Form->control('email') ?>
<?= $this->Form->control('password') ?>
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>
The email is stored as a user id and the password is stored in the password table Address is an attribute in the email table that stores the actual email address Password is where pw is the stores
The authentication component accepts an address - which
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
//here we define what is compared to be authenticated
'username' => 'address',
'password' => 'password'
]
]...
The login function is similar to the regular one:
public function login()
{
if ($this->request->is('post')) {
//PUT IN STUFF HERE
$user = $this->Auth->identify();
if ($user) {
$user->last_login = Time::now();//dont put this above uif statement, will automatically create a default object
$this->Auth->setUser($user);
$this->Flash->success('You have been successfully logged in.');
$this->log("Login success", 'debug');
//redirect after login
return $this->redirect($this->Auth->redirectUrl('/users/index'));
}
$this->Flash->error('Your username or password is incorrect.');
$this->log("Login FAILURE", 'debug');
}
}`
The way I see it we are either comparing the email id or getting a form to directly view the "Associated Classes" attribute. How can one point the authentication to an attribute in another table such as
thank
source to share
I would suggest a less intrusive way, that is, use a custom search that contains / concatenates the users table, and sets the field password
in the main query using the alias or main object as a virtual field, this way the inline authenticator fetch the data it needs, which is all it has value for the authenticator.
For example, in your class, EmailsTable
add a crawler like this that picks the correct value for the field password
:
public function findAuth(\Cake\ORM\Query $query, array $options)
{
return
$this
->find()
->select([
'Emails.id',
'Emails.address', // you may want to alias this one too
'password' => 'Users.password'
])
->leftJoinWith('Users')
->where([
// the options is always named `username`, this is
// not affected by the `fields` configuration
'Emails.address' => $options['username']
]);
}
With a search like this, all you have to do is configure the parameters fields
, userModel
and finder
for the auth component, for example:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
// set the field to `email`, just like in your form
'username' => 'email'
],
'userModel' => 'Emails',
'finder' => 'auth'
]
// ...
]
]);
This example assumes that it Emails
is linked Users
through an association belongsTo
or hasOne
using a strategy join
.
Also note that the field is username
set to a value email
exactly the same as in your example form, you can also set as address
(or whatever you really like), this will not affect the search query as it creates a new query and uses the username value that was retrieved from the request data via the configured field (the retrieved value will always be passed to username
) of the array $options
, unless it finder
is an array that already has a named key username
).
see also
source to share
You need to create Custom Authentication Objects for this
Boot component
$this->loadComponent('Auth', [
'authenticate' => [
'CustomForm' => [
'fields' => [
'username' => 'address',// Field in your emails table
'password' => 'password',// Field in your users table
'myAssoc'=>'Users'// Custom Filed to get association
],
'userModel' => 'Emails'
]...
Create a CustomFormAuthenticate.php file in / src / Auth / folder
<?php
namespace App\Auth;
use Cake\Auth\FormAuthenticate;
use Cake\Utility\Inflector;
class CustomFormAuthenticate extends FormAuthenticate
{
public function _findUser($username, $password = null)
{
$result = $this->_query($username);
$myAssoc = false;
if (!empty($this->_config['fields']['myAssoc'])) {
$myAssoc = $this->_config['fields']['myAssoc'];
$result->contain([$myAssoc]);
}
$result = $result->first();
if (empty($result)) {
return false;
}
if ($password !== null) {
$hasher = $this->passwordHasher();
if($myAssoc !== false){
$hashedPassword = $result->{Inflector::underscore(Inflector::singularize($myAssoc))}[$this->_config['fields']['password']];
} else {
$hashedPassword = $result->get($this->_config['fields']['password']);
}
if (!$hasher->check($password, $hashedPassword)) {
return false;
}
$this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
$result->unsetProperty($this->_config['fields']['password']);
}
debug($result);
return $result->toArray();
}
}
Make sure you have an email model user association in your EmailTable.php
$this->hasOne('Users', [
'foreignKey' => 'email_id'
]);
On the login page
<?= $this->Form->create() ?>
<?= $this->Form->control('address') ?> // Field in your email table
<?= $this->Form->control('password') ?>// Field in your users table
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>
I tested it and it worked for me.
source to share